模拟静态方法
Mocking a static method
以下是我要测试的方法。我正在使用 TestNG 框架进行单元测试。
class Random{
List<String> namesOfLinks;
public List<String> methodIwantToTest(List<String> cktNames) {
Map<String, Graph> maps = DataBaseReader.getGraphs(cktNames);
for (Entry<String, Graph> entry : maps.entrySet()) {
graphList.add(entry.getValue().getName());
}
}
return namesOfLinks;
}
我正在为上面class中的方法"methodIwantToTest"编写测试用例。我可以提供一些虚拟的 cktNames 并获取如下所示的执行方法。
@Test (dataProvider = "dp")
public void test_methodIwantToTest(List<String> cktNames, List<String> expectedLinkNames){
Random rm = new Random();
List<String> actual = rm.methodIwantToTest(cktNames);
Assert.assertEquals(actual,expectedLinkNames);
}
问题来了。当我在 'rm' 引用上调用它时实际方法正在执行时,它有一个对另一个 API 的静态方法调用。它必须 return 一些东西才能让我的 "method" 工作。我在互联网上搜索并找到 "easymock" 作为解决方案。但是我无法使用 "easyMock" 来模拟静态方法 (DataBaseReader.getGraphs())。我必须模拟该方法,以便它 return 是定义类型的映射。任何建议都会很棒。
谢谢!!
其他问题涉及如何测试静态方法。但是我的是关于在测试实例方法时模拟静态方法。
你需要PowerMock to do mock static methods directly. See https://github.com/jayway/powermock/wiki/TestNG_usage
我建议结合使用适配器模式和依赖注入技术。创建一个包含您要模拟的所有方法的接口:
public interface IDatabase {
Map<String, Graph> getGraphs(List<String> names);
}
显然,Database
并没有实现你刚刚发明的接口(反正方法是 static
),但是你可以创建一个适配器 class:
public class DataBaseReaderAdapter implements IDatabase {
public Map<String, Graph> getGraphs(List<String> names) {
return DataBaseReader.getGraphs(names);
}
}
将此 class 的实例作为要测试的 class 中的构造函数参数:
public class Random {
private readonly IDatabase _database;
public Random(IDatabase database) {
_database = database;
}
}
以及何时调用方法:
Map<String, Graph> maps = _database.getGraphs(cktNames);
在您的测试中,使用任何模拟框架创建 IDatabase
的模拟,并将该模拟传递给 Random
。
虽然这种技术乍一看似乎很复杂,但它往往会带来更好的设计,其中 class 的依赖关系更加明显,一切都变得更容易测试。
以下是我要测试的方法。我正在使用 TestNG 框架进行单元测试。
class Random{
List<String> namesOfLinks;
public List<String> methodIwantToTest(List<String> cktNames) {
Map<String, Graph> maps = DataBaseReader.getGraphs(cktNames);
for (Entry<String, Graph> entry : maps.entrySet()) {
graphList.add(entry.getValue().getName());
}
}
return namesOfLinks;
}
我正在为上面class中的方法"methodIwantToTest"编写测试用例。我可以提供一些虚拟的 cktNames 并获取如下所示的执行方法。
@Test (dataProvider = "dp")
public void test_methodIwantToTest(List<String> cktNames, List<String> expectedLinkNames){
Random rm = new Random();
List<String> actual = rm.methodIwantToTest(cktNames);
Assert.assertEquals(actual,expectedLinkNames);
}
问题来了。当我在 'rm' 引用上调用它时实际方法正在执行时,它有一个对另一个 API 的静态方法调用。它必须 return 一些东西才能让我的 "method" 工作。我在互联网上搜索并找到 "easymock" 作为解决方案。但是我无法使用 "easyMock" 来模拟静态方法 (DataBaseReader.getGraphs())。我必须模拟该方法,以便它 return 是定义类型的映射。任何建议都会很棒。 谢谢!!
其他问题涉及如何测试静态方法。但是我的是关于在测试实例方法时模拟静态方法。
你需要PowerMock to do mock static methods directly. See https://github.com/jayway/powermock/wiki/TestNG_usage
我建议结合使用适配器模式和依赖注入技术。创建一个包含您要模拟的所有方法的接口:
public interface IDatabase {
Map<String, Graph> getGraphs(List<String> names);
}
显然,Database
并没有实现你刚刚发明的接口(反正方法是 static
),但是你可以创建一个适配器 class:
public class DataBaseReaderAdapter implements IDatabase {
public Map<String, Graph> getGraphs(List<String> names) {
return DataBaseReader.getGraphs(names);
}
}
将此 class 的实例作为要测试的 class 中的构造函数参数:
public class Random {
private readonly IDatabase _database;
public Random(IDatabase database) {
_database = database;
}
}
以及何时调用方法:
Map<String, Graph> maps = _database.getGraphs(cktNames);
在您的测试中,使用任何模拟框架创建 IDatabase
的模拟,并将该模拟传递给 Random
。
虽然这种技术乍一看似乎很复杂,但它往往会带来更好的设计,其中 class 的依赖关系更加明显,一切都变得更容易测试。