Как сообщить моктовому объекту Mockito возвратить что-то другое при следующем его вызове?
Итак, я создаю mock-объект как статическую переменную на уровне класса, например... В одном тесте я хочу, чтобы 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.
}
}
Во втором тесте, я все еще получаю 0 в качестве значения при вызове testObj.bar()... Каков наилучший способ решить эту проблему? Обратите внимание, что я знаю, что в каждом тесте я мог бы использовать различный макет Foo
, однако мне нужно связать несколько запросов с mockFoo
, то есть мне нужно будет выполнить цепочку в каждом тесте.
Ответы
Ответ 1
Прежде всего, не делайте макет статичным. Сделайте это частным полем. Просто поставьте свой класс setUp в @Before
not @BeforeClass
. Это может быть пучок, но это дешево.
Во-вторых, способ, которым у вас есть это прямо сейчас, - это правильный способ заставить макет вернуть что-то другое в зависимости от теста.
Ответ 2
Вы также можете Последовательные последовательные вызовы (# 10 в 2.8.9 api). В этом случае вы будете использовать несколько вызовов thenReturn или один вызов thenReturn с несколькими параметрами (varargs).
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
}
}
Ответ 3
Для всех, кто ищет что-то для возврата, а затем для другого исключения броска вызова:
when(mockFoo.someMethod())
.thenReturn(obj1)
.thenReturn(obj2)
.thenThrow(new RuntimeException("Fail"));
или же
when(mockFoo.someMethod())
.thenReturn(obj1, obj2)
.thenThrow(new RuntimeException("Fail"));
Ответ 4
Или даже чище:
when(mockFoo.someMethod()).thenReturn(obj1, obj2);
Ответ 5
Для тех, кто использует spy() и doReturn() вместо метода when():
то, что вам нужно для возврата разных объектов при разных вызовах, это:
doReturn(obj1).doReturn(obj2).when(this.client).someMethod();
.
Для классических издевательств:
when(this.client.someMethod()).thenReturn(obj1, obj2);