使用mockito模拟嵌套方法调用

时间:2017-01-19 01:39:09

标签: java methods junit mocking mockito

我有4个课程让我们说A,B,C,D各自调用另一个方法。

现在我嘲笑了A类,想要使用mockito模拟一个方法

A a = Mockito.mock(A.class);

并希望在递归方法调用(如

)上获得“foo”

a.getB().getC().getD()应该返回"foo"

我试过

  

当(a.getB()GETC()GETD()。)thenReturn( “富”);

但得到了nullPointerException

然后我试了

  

doReturn( “富”)时(a.getB()GETC()GETD());

然后我得到org.mockito.exceptions.misusing.UnfinishedStubbingException:

我知道我可以创建B,C和D的对象,或者甚至可以编写类似

的对象
  

B b = mock(B.class)或A.setB(new B())

等等。

但我不能一次性做到这一点? 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:40)

来自评论:

添加RETURNS_DEEP_STUBS就可以了:

{{1}}

答案 1 :(得分:11)

Abhijeet的技术答案在技术上是正确的,但重要的是要理解:你应该这样做。

您的生产"代码严重违反Law of Demeter:您的A类知道必须获得B才能获得C才能获得D.

这只会导致所有这些类之间的超紧密耦合。不是个好主意。

从这个意义上说:你应该看到这样一个事实:你需要在这里做一些特殊的事情来让你的测试工作,这实际上表明你的生产代码做了超出正常的事情。

所以,而不是"修复"您的测试设置,请考虑解决真正的问题。这就是生产代码设计

对于记录:getB()。getC()。getD()不是"递归"呼叫;它更像是一个流畅的"方法调用的链接。如上所述:是一件好事。

答案 2 :(得分:0)

尝试创建每个嵌套对象的模拟,然后模拟每个对象调用的单个方法。

如果目标代码如下:

public Class MyTargetClass {

    public String getMyState(MyClass abc){

       return abc.getCountry().getState();
    }
}

然后为了测试这一行,我们可以为每个单独的嵌套对象创建模拟,如下所示:

public Class MyTestCase{

@Mock
private MyTargetClass myTargetClassMock;

@Mock
private MyClass myclassMockObj;

@Mock
private Country countryMockObj;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

    @Test
    public void test01(){

       when(myclassMockObj.getCountry()).thenReturn(countryMockObj);
       when(countryMockObj.getState()).thenReturn("MY_TEST_STATE");
       Assert.assertEquals("MY_TEST_STATE", myTargetClassMock.getMyState(myclassMockObj));
    }
}