如何告诉一个Mockito模拟对象返回不同的东西,下次它被调用?

因此,我在类级别上创建一个模拟对象作为静态变量,就像这样……在一个测试中,我希望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中链接多个请求,这意味着我必须在每个测试中进行链接。

276087 次浏览

首先,不要让模拟是静态的。将其设置为私有字段。只要把你的setUp类放在@Before而不是@BeforeClass。它可能会运行很多次,但很便宜。

其次,您现在拥有它的方式是让mock根据测试返回不同内容的正确方法。

你也可以存根连续呼叫 . (2.8.9 api中的#10)。在这种情况下,您将使用多个thenReturn调用或一个带有多个参数(varargs)的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
}
}

对于使用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);

对于所有搜索返回一些东西,然后另一个调用抛出异常:

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

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

或者,更简洁:

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