想象下面的类
public class ClassToBeTested{
private AnotherClass otherClass;
public void methodToBeTested(){
otherClass = new AnotherClass();
String temp = otherClass.someMethod()
// ...some other code that depends on temp
}
}
现在,如果methodToBeTested
被设计为接受AnotherClass
的实例,我可以很容易地创建AnotherClass
的模拟,并告诉Mockito在调用someMethod()
时返回一个我喜欢的值。然而,由于上述代码是AFAIK设计的,因此不可能模拟AnotherClass
,并且测试此方法将取决于someMethod()
返回的内容。
无论如何,我可以测试上面的代码不依赖于什么someMethod()
返回使用Mockito或任何其他框架?
如果可用,您可以使用Spring ReflectionTestUtils
setField
方法:
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html setField % 28 java . lang . object, % 20以% 20 java . lang . object % 29
如果不自己写的话,可以直接使用反射,这里有一些信息:
http://www.java2s.com/Code/Java/Reflection/Setprivatefieldvalue.htm如下所示,您需要额外的错误处理才能使其正常工作:
public void setField(Object obj, String fieldName, Object value) {
Field f = obj.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(obj, value);
}
可以这样调用:
setField(objUnderTest, "fieldToSet", mockObject);
编辑
我刚刚注意到你在方法中实例化了它。如果这是绝对必要的,那么你应该遵循cyroxx发布的可能重复的链接。虽然这种做法通常是糟糕设计的标志,所以如果你可以把它去掉,我会的。
根据另一个答案中的建议通过反射设置字段可以工作。
但是,如果您经常做这种事情,我建议使用PowerMock(与Mockito结合使用)或JMockIt来实现这一点。两者都允许模拟构造函数、静态函数、final字段……简而言之,什么都可以。对于遗留代码非常有用。
然而,当你在编写新代码时,你的类依赖于另一个你想用这种方式隔离的类,你应该考虑改变设计,使其他对象被传递给你的类,而不是被它实例化。搜索"Dependency injection",你会发现很多…
作为快速修复,我通常将调用包装到new
:
protected newAnotherClass() { return new AnotherClass(); }
这样,我就可以从单元测试中重写这个方法。它很脏,但是很快:-)
这是一个JMockit测试,它可以做你想要的,非常简单:
@Test
public void testTheMethodToBeTested(@Mocked final AnotherClass dep)
{
new NonStrictExpectations() {{ dep.someMethod(); result = "whatever"; }};
new ClassToBeTested().methodToBeTested();
new Verifications() {{
// verify other calls to `dep`, if applicable...
}};
}