Java 如何告诉 Mockito 模拟对象在下次调用时返回不同的内容?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4216569/
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-14 14:41:10  来源:igfitidea点击:

How to tell a Mockito mock object to return something different the next time it is called?

javaunit-testingjunitmockingmockito

提问by Polaris878

So, I'm creating a mock object as a static variable on the class level like so... In one test, I want Foo.someMethod()to return a certain value, while in another test, I want it to return a different value. The problem I'm having is that it seems I need to rebuild the mocks to get this to work correctly. I'd like to avoid rebuilding the mocks, and just use the same objects in each test.

所以,我正在创建一个模拟对象作为类级别上的静态变量,就像这样......在一个测试中,我想Foo.someMethod()返回一个特定的值,而在另一个测试中,我希望它返回一个不同的值。我遇到的问题是,似乎我需要重建模拟才能使其正常工作。我想避免重建模拟,而只是在每个测试中使用相同的对象。

class TestClass {

    private static Foo mockFoo;

    @BeforeClass
    public static void setUp() {
        mockFoo = mock(Foo.class);
    }

    @Test
    public void test1() {
        when(mockFoo.someMethod()).thenReturn(0);

        TestObject testObj = new TestObject(mockFoo);

        testObj.bar(); // calls mockFoo.someMethod(), receiving 0 as the value

    }

    @Test
    public void test2() {
        when(mockFoo.someMethod()).thenReturn(1);

        TestObject testObj = new TestObject(mockFoo);

        testObj.bar(); // calls mockFoo.someMethod(), STILL receiving 0 as the value, instead of expected 1.

    }

}

In the second test, I'm still receiving 0 as the value when testObj.bar() is called... What is the best way to resolve this? Note that I know I could use a different mock of Fooin each test, however, I have to chain multiple requests off of mockFoo, meaning I'd have to do the chaining in each test.

在第二个测试中,当调用 testObj.bar() 时,我仍然收到 0 作为值......解决这个问题的最佳方法是什么?请注意,我知道我可以Foo在每个测试中使用不同的模拟,但是,我必须将多个请求从mockFoo链接起来,这意味着我必须在每个测试中进行链接。

采纳答案by shoebox639

First of all don't make the mock static. Make it a private field. Just put your setUp class in the @Beforenot @BeforeClass. It might be run a bunch, but it's cheap.

首先,不要使模拟静态。使其成为私人领域。只需将您的 setUp 类放在@Beforenot 中@BeforeClass。它可能会运行一堆,但它很便宜。

Secondly, the way you have it right now is the correct way to get a mock to return something different depending on the test.

其次,您现在拥有的方式是让模拟返回不同内容的正确方法,具体取决于测试。

回答by Tony R

You could also Stub Consecutive Calls(#10 in 2.8.9 api). In this case, you would use multiple thenReturncalls or one thenReturncall with multiple parameters (varargs).

您还可以存根连续调用(2.8.9 api 中的#10)。在这种情况下,您将使用多个thenReturn调用或一个带有多个参数(可变参数)的thenReturn调用。

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;

public class TestClass {

    private Foo mockFoo;

    @Before
    public void setup() {
        setupFoo();
    }

    @Test
    public void testFoo() {
        TestObject testObj = new TestObject(mockFoo);

        assertEquals(0, testObj.bar());
        assertEquals(1, testObj.bar());
        assertEquals(-1, testObj.bar());
        assertEquals(-1, testObj.bar());
    }

    private void setupFoo() {
        mockFoo = mock(Foo.class);

        when(mockFoo.someMethod())
            .thenReturn(0)
            .thenReturn(1)
            .thenReturn(-1); //any subsequent call will return -1

        // Or a bit shorter with varargs:
        when(mockFoo.someMethod())
            .thenReturn(0, 1, -1); //any subsequent call will return -1
    }
}

回答by fl0w

For Anyone using spy()and the doReturn() instead of the when() method:

对于使用 spy()和 doReturn() 而不是 when() 方法的任何人:

what you need to return different object on different calls is this:

你需要在不同的调用中返回不同的对象是这样的:

doReturn(obj1).doReturn(obj2).when(this.spyFoo).someMethod();

.

.

For classic mocks:

对于经典模拟:

when(this.mockFoo.someMethod()).thenReturn(obj1, obj2);

or with an exception being thrown:

或抛出异常:

when(mockFoo.someMethod())
        .thenReturn(obj1)
        .thenThrow(new IllegalArgumentException())
        .thenReturn(obj2, obj3);

回答by Nagy Attila

For all who search to return something and then for another call throw exception:

对于所有搜索返回内容然后另一个调用抛出异常的人:

    when(mockFoo.someMethod())
            .thenReturn(obj1)
            .thenReturn(obj2)
            .thenThrow(new RuntimeException("Fail"));

or

或者

    when(mockFoo.someMethod())
            .thenReturn(obj1, obj2)
            .thenThrow(new RuntimeException("Fail"));

回答by Pedro H

Or, even cleaner:

或者,甚至更清洁:

when(mockFoo.someMethod()).thenReturn(obj1, obj2);