Java Mockito:使用“thenReturn”中的方法返回模拟不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34005168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:13:55  来源:igfitidea点击:

Mockito: using a method in "thenReturn" to return a mock doesn't work

javaunit-testingmockingmockito

提问by LawrenceWeetman

I have encountered what I assume might be a bug with Mockito, but was wondering if anyone else can shed light as to why this test doesn't work.

我遇到了我认为可能是 Mockito 的错误,但想知道是否还有其他人可以解释为什么这个测试不起作用。

Basically, I have two objects, like this:

基本上,我有两个对象,如下所示:

public class FirstObject {
    private SecondObject secondObject;
    public SecondObject getSecondObject() { return secondObject; }
}

public class SecondObject {
    private String name;
    public String getName() { return name; }
}

The first object is mocked via annotation and the before method:

第一个对象是通过注解和 before 方法模拟的:

@Mock
FirstObject mockedFirstObject;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

The second object is mocked in a method:

第二个对象在一个方法中被模拟:

public SecondObject setupMockedSecondObject() {
    SecondObject secondObject = Mockito.mock(SecondObject.class);
    Mockito.when(secondObject.getName()).thenReturn("MockObject");
    return secondObject;
}

When thenReturncontains a direct call to this method to setup and obtain a mock of the second object, it fails:

thenReturn包含对此方法的直接调用以设置和获取第二个对象的模拟时,它会失败:

@Test
public void notWorkingTest() {
    Mockito.when(mockedFirstObject.getSecondObject()).thenReturn(setupMockedSecondObject());
    Assert.assertEquals(mockedFirstObject.getSecondObject().getName(), "MockObject");
}

But, when the mock returned by the same method is assigned to a local variable, which is used in thenReturn, it works:

但是,当由相同方法返回的模拟被分配给在 中使用的局部变量时thenReturn,它会起作用:

@Test
public void workingTest() {
    SecondObject mockedSecondObject = setupMockedSecondObject();
    Mockito.when(mockedFirstObject.getSecondObject()).thenReturn(mockedSecondObject);
    Assert.assertEquals(mockedFirstObject.getSecondObject().getName(), "MockObject");
}

Are we doing something wrong or is this indeed a bug/limitation in Mockito? Is there a deliberate reason for this not working?

我们做错了什么还是这确实是 Mockito 中的错误/限制?这是否有故意的原因不起作用?

采纳答案by Tunaki

This is indeed a limitation of Mockito, and it is referenced in their FAQ:

这确实是 Mockito 的一个限制,在他们的 FAQ 中被引用:

Can I thenReturn()an inlined mock()?

Unfortunately you cannot do this:

when(m.foo()).thenReturn(mock(Foo.class));
//                         ^

The reason is that detecting unfinished stubbing wouldn't work if we allow above construct. We consider is as a 'trade off' of framework validation (see also previous FAQ entry). However you can slightly change the code to make it working:

//extract local variable and start smiling:
Foo foo = mock(Foo.class);
when(m.foo()).thenReturn(foo);

thenReturn()可以内联mock()吗?

不幸的是你不能这样做:

when(m.foo()).thenReturn(mock(Foo.class));
//                         ^

原因是如果我们允许上述构造,检测未完成的存根将不起作用。我们认为这是框架验证的“权衡”(另请参阅之前的常见问题解答条目)。但是,您可以稍微更改代码以使其正常工作:

//extract local variable and start smiling:
Foo foo = mock(Foo.class);
when(m.foo()).thenReturn(foo);

The workaround, as mentioned, is to store the desired returned value in a local variable, like you have done.

如前所述,解决方法是将所需的返回值存储在局部变量中,就像您所做的那样。

The way I understand it is that Mockito validates the usage you make of it every time you call its methods. When another method is called during an on-going stubbing process, you are breaking its validation process.

我的理解是,每次调用它的方法时,Mockito 都会验证你对它的使用。在正在进行的存根过程中调用另一个方法时,您正在破坏其验证过程。