假设我有一个这样的类:
public class MyClass {
Dao dao;
public String myMethod(Dao d) {
dao = d;
String result = dao.query();
return result;
}
}
我想用mockito测试它。所以我创建了一个模拟对象,并调用方法以这种方式进行测试:
Dao mock = Mockito.mock(Dao.class);
Mockito.when(mock.myMethod()).thenReturn("ok");
new MyClass().myMethod(mock);
但是,假设我有一个类似的课程:
public class MyClass {
Dao dao = new Dao();
public String myMethod() {
String result = dao.query();
return result;
}
}
现在我无法将我的模拟作为参数传递,所以我将如何测试我的方法?有人可以举个例子吗?
答案 0 :(得分:10)
从根本上说,您尝试使用替代实现替换私有字段,这意味着您违反了封装。您唯一的另一个选择是重新构建类或方法,使其更好地设计用于测试。
评论中有很多简短的答案,所以我在这里汇总它们(并添加我自己的几个)作为社区Wiki。 如果您有任何其他选择,请随时在此处添加。
创建一个依赖注入的覆盖或静态方法,它接受DAO,并使公共实例方法委托给它。而是测试更灵活的方法。
public String myMethod() { return myMethod(dao); }
String myMethod(Dao dao) { /* real implementation here */ }
请注意,如果将测试放在同一个Java包中(可能在单独的源代码树中),其中一些可以是package-private进行测试。在所有情况下,良好的名称和文档都有助于明确您的意图。
Dao
构造函数替换为您选择的模拟。 (Dave Newton)答案 1 :(得分:2)
public class MyClassTest {
MyClass myClass = new MyClass();
Dao dao = Mockito.mock(Dao.class);
public void testMyMethod() {
Field field = myClass.getClass().getDeclaredField("dao");
field.setAccessible(true);
field.set(myClass, dao);
//Do the test...
}
}
编辑:正如评论中所述,这假定您不会更改dao
字段的名称。然后获取所有字段Field[] fields = myClass.getClass().getDeclaredFields();
并迭代它们,获得Dao类型的字段可能是个好主意。然后按上述步骤进行。这样,您的测试就不再依赖于您的字段名称了。