简体   繁体   English

使用 mockito 模拟嵌套方法调用

[英]mock nested method calls using mockito

I have got 4 classes lets says A, B, C, D each calling on methods from another one.我有 4 个类,可以说 A、B、C、D,每个类都调用另一个类的方法。

now I have mocked class A, and want to mock a method using mockito现在我已经模拟了 A 类,并想使用 mockito 模拟一个方法

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

and want to get "foo" on recursive method calls like并希望在递归方法调用上获得“foo”,例如

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

I tried我试过

when(a.getB().getC().getD()).thenReturn("foo"); when(a.getB().getC().getD()).thenReturn("foo");

but got nullPointerException但得到了 nullPointerException

then I tried然后我试过了

doReturn("foo").when(a.getB().getC().getD()); doReturn("foo").when(a.getB().getC().getD());

then I got org.mockito.exceptions.misusing.UnfinishedStubbingException:然后我得到了org.mockito.exceptions.misusing.UnfinishedStubbingException:

I know I can create objects of B, C and D, or can even write something like我知道我可以创建 B、C 和 D 的对象,甚至可以写一些类似的东西

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

and so on.等等。

But can't I do that in a single shot?但是我不能一次性做到吗? Any help would be appreciated.任何帮助,将不胜感激。

添加RETURNS_DEEP_STUBS 可以解决问题

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

The answer by Abhijeet is technically correct, but it is important to understand: you should not be doing this. Abhijeet 的回答在技术上是正确的,但重要的是要理解:你应该这样做。

Your "production" code is heavily violating the Law of Demeter : your class A should not know that it has to get a B to get a C to get a D.您的“生产”代码严重违反了迪米特法则:您的 A 班应该知道它必须获得 B 才能获得 C 才能获得 D。

That simply leads to super tight coupling between all these classes.这只会导致所有这些类之间的超紧耦合。 Not a good idea.不是个好主意。

In that sense: you should see the fact that you need to do special things here to get your test working as an indication that your production code does something that is out of the normal .从这个意义上说:您应该看到这样一个事实,即您需要在这里做一些特殊的事情才能让您的测试工作,这表明您的生产代码做了一些不正常的事情。

So, instead of "fixing" your test setup, consider addressing the real problem .因此,与其“修复”您的测试设置,不如考虑解决真正的问题 And that is the design of your production code !这就是您的生产代码设计

And for the record: getB().getC().getD() is not a "recursive" call;为了记录: getB().getC().getD() 不是“递归”调用; it is more of a "fluent" chaining of method calls.它更像是一个“流畅”的方法调用链。 And as said: that is not a good thing.正如所说:这不是一件好事。

Try by creating mock of each of the nested object and then mock the individual method called by each of these object.尝试创建每个嵌套对象的模拟,然后模拟每个这些对象调用的各个方法。

If the target code is like:如果目标代码是这样的:

public Class MyTargetClass {

    public String getMyState(MyClass abc){

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

Then to test this line we can create mocks of each of the individual nested objects like below:然后为了测试这一行,我们可以为每个单独的嵌套对象创建模拟,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM