Mockito - 深刻的顽固

时间:2012-11-21 16:50:50

标签: java junit mockito

我正在使用Mockito来测试我的课程。我正在尝试使用Deep存根,因为我没有在Mockito中的另一个模拟对象中注入Mock。

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;

我现在想要的是在调用somehelper对象时调用invokeMeth()方法,在这种情况下它调用真实方法。

when(somehelper.invokeMeth(isA(RequestObject.class)))
    .thenCallRealMethod();

我希望在这种情况下webServiceTemplate不为null。

但是当代码尝试执行行

时,我得到一个Nullpointer异常
webServiceTemplate.marshalSendAndReceive(t);

任何线索我如何能够访问一个深度模拟对象(即在mock中进行模拟 - 在这种情况下是someserper mock中的webserviceTemplete模拟)然后应用when条件来抛出WebserviceIOException? 我希望这样,以便我可以测试MyService.create(),以便在向代码抛出WebServiceIOException时检查它是否正常运行。

1 个答案:

答案 0 :(得分:3)

是的,当然,你正在混合真实对象和模拟。另外使用thenCallRealMethod lloks就像部分模拟一样,这里感觉不对,这也就是javadoc of this method对此的讨论也就不足为奇了。

我明确应该强调你,而不是设计明智,有一个模拟返回模拟通常是一种气味。更准确地说,您正在违反得墨忒耳法,或者不遵循告诉,不要求原则。

任何查看代码我都不知道为什么代码需要模拟WebServiceTemplate。您想要对MyService进行单元测试,但我看不到与WebServiceTemplate的关系。相反,你应该专注于与你帮助的互动。单独测试SomeHelper ,您可以检查SomeHelperWebServiceTemplate之间的互动。

以下是我如何看待这件事的一个小例子:

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));
}

那些寻找真实用例的方法?

希望有所帮助