249

所以,我在类级别创建一个模拟对象作为静态变量,就像这样......在一个测试中,我想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.

    }

}

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

4

5 回答 5

498

您还可以存根连续调用(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
    }
}
于 2011-05-19T21:32:59.973 回答
56

对于所有搜索返回某些内容然后再次调用抛出异常的人:

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

或者

when(mockFoo.someMethod())
        .thenReturn(obj1, obj2)
        .thenThrow(new RuntimeException("Fail"));
于 2018-05-24T12:09:04.730 回答
48

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

其次,你现在拥有它的方式是让一个模拟返回不同的东西的正确方法,具体取决于测试。

于 2010-11-18T15:45:52.697 回答
36

或者,更清洁:

when(mockFoo.someMethod()).thenReturn(obj1, obj2);
于 2018-10-24T11:23:46.303 回答
24

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

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

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

.

对于经典模拟:

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

或抛出异常:

when(mockFoo.someMethod())
        .thenReturn(obj1)
        .thenThrow(new IllegalArgumentException())
        .thenReturn(obj2, obj3);
于 2018-03-07T16:41:43.033 回答