Подтвердить что ты не робот

Mockito: использование метода "thenReturn" для возврата макета не работает

Я столкнулся с тем, что, по моему мнению, может быть ошибкой с Mockito, но задавался вопросом, может ли кто-нибудь еще пролить свет на то, почему этот тест не работает.

В принципе, у меня есть два объекта, например:

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

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

Первый объект издевается через аннотацию и метод before:

@Mock
FirstObject mockedFirstObject;

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

Второй объект издевается по методу:

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

Когда thenReturn содержит прямой вызов этого метода для настройки и получения макета второго объекта, он терпит неудачу:

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

Но, когда макет, возвращенный тем же методом, назначается локальной переменной, которая используется в thenReturn, она работает:

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

Мы делаем что-то неправильно или это действительно ошибка/ограничение в Mockito? Есть ли умышленная причина, по которой это не работает?

4b9b3361

Ответ 1

Это действительно ограничение Mockito, и на него ссылаются в их FAQ:

Могу ли я thenReturn() встроить mock()?

К сожалению, вы не можете этого сделать:

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

Причина в том, что обнаружение незавершенного штамповки не будет работать, если мы разрешим эту конструкцию. Мы рассматриваем это как "компромисс" валидации структуры (см. Также предыдущую запись в FAQ). Однако вы можете слегка изменить код, чтобы он работал:

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

Обходной путь, как уже упоминалось, заключается в сохранении желаемого возвращаемого значения в локальной переменной, как и вы.

То, как я понимаю, это то, что Mockito проверяет использование, которое вы делаете, каждый раз, когда вы вызываете его методы. Когда вызывается другой метод во время текущего процесса прерывания, вы нарушаете его процесс проверки.