我正在使用Mockito来测试我的课程。我正在尝试使用深度存根,因为我没有办法在 Mockito 中的另一个模拟对象中注入模拟。
class MyService{
@Resource
SomeHelper somehelper;
public void create()
{
//....
somehelper.invokeMeth(t);
}
}
class SomeHelper{
@Resource
private WebServiceTemplate webServiceTemplate;
public void invokeMeth(T t)
{
try{
//...
webServiceTemplate.marshalSendAndReceive(t);
}catch (final WebServiceIOException e) {
throw new MyAppException("Service not running");
}
}
}
现在我正在尝试对 MyService 类的 create() 方法进行单元测试。我为SomeHelper注入了一个模拟,如下所示
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
SomeHelper somehelper;
我现在想要的是当 invokeMeth() 方法在模拟的某个助手对象上被调用时,在这种情况下它调用了真正的方法。
when(somehelper.invokeMeth(isA(RequestObject.class)))
.thenCallRealMethod();
我期望在这种情况下网络服务模板不为空。
但是,当代码尝试执行该行时,我收到 Nullpointer 异常
webServiceTemplate.marshalSendAndReceive(t);
任何线索我可以访问一个深度模拟对象(即模拟中的模拟 - 在这种情况下,webserviceTemplete 模拟在某个助手模拟中),然后应用 when 条件来抛出 WebserviceIOException?我想要这个,以便我可以测试 MyService.create() 以检查它在 WebServiceIOException 被抛出代码时的行为是否正确。
是的,当然,您正在混合真实对象和模拟。另外,使用thenCallRealMethod
lloks就像部分模拟一样,在这里感觉不对,难怪这种方法的javadoc也谈到了这一点。
我肯定应该强调你,设计明智,有一个模拟返回一个模拟通常是一种气味。更准确地说,你违反了得墨忒耳定律,或者没有遵循"告诉,不问"原则。
任何看你的代码,我不知道为什么代码需要嘲笑WebServiceTemplate
.你想MyService
单元测试,我看不出和WebServiceTemplate
有什么关系。相反,您应该只关注与助手的交互。单元测试SomeHelper
单独进行,您可以在其中检查SomeHelper
和WebServiceTemplate
之间的交互。
以下是我如何看待这件事的一个小例子:
public void ensure_helper_is_used_to_invoke_a_RequestObject() {
// given a service that has an helper collaborator
... other fixture if necessary
// when
myService.behaviorToTest();
// then
verify(someHelperMock).invokeMeth(isA(RequestObject.class));
}
那些如何寻找您的真实用例?
希望有帮助