Estou usando o Mockito para criar testes unitários para Java, mas encontrei um problema estranho
Digamos que eu tenha um ObjectUnderTest
com um mainMethod
e uma dependência Dependency
simulada, com um método mockedMethod
:
class ObjectUnderTest {
private Dependency dependency;
public mainMethod() {
// some logic...
// now calling the `mockedMethod` with some retry config
// this is pseudocode but you get it
retryOn(RETRY_TIMES, SOME_INTERVAL,
() -> dependency.mockedMethod("mockedValue") != null, // do this each retry and returns when dependency returns non-null
() -> new SomeException("kaboom") // throw some exception after retry exhausted
);
// some other logic...
}
}
class MyTestClass {
// say Dependency has a method
// public ReturnValueDep mockedMethod(String)
private Dependency mockedDep;
private ObjectUnderTest testObj;
@BeforeEach
public void setUp() {
// set up mocks...
this.testObj = new ObjectUnderTest(mockedDep, // other params...
);
}
@Test
public void thisTestFailed() {
final OngoingStubbing<ReturnValueDep> stubbing = lenient().when(mockedDep.mockedMethod(eq("mockedValue")));
IntStream.rangeClosed(0, RETRY_TIMES).forEach((int i) -> stubbing.thenReturn(null));
stubbing.thenReturn(SOME_NON_NULL_VALUE);
assertThrows(SomeException.class, () -> testObj.mainMethod());
}
}
No entanto, estou recebendo um erro do Mockito como este:
=> org.mockito.exceptions.base.MockitoException:
[java] Incorrect use of API detected here:
[java] -> at xxxxxx (redacted)
[java] You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once.
[java] Examples of correct usage:
[java] when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);
[java] when(mock.isOk()).thenReturn(true, false).thenThrow(exception);
Alguma ideia de por que isso não é permitido? Isso é tão estranho.
Adicionar lenient()
a ele não resolve o erro. Parece que não pode ser contornado.
A mensagem de erro é bem clara sobre o problema: você não pode chamar
.thenReturn
a mesmaOngoingStubbing
instância várias vezes. Então isso é proibido:Cada
.thenReturn
chamada retorna uma novaOngoingStubbing
instância, que você pode usar para encadear as chamadas stub. Isso funciona sem problemas:Com um loop simples e uma variável não final, isso é trivial de escrever – basta reatribuir a
stubbing
variável:Se você precisar usar um fluxo, os redutores serão úteis:
Parece que você já tem uma solução na descrição do erro: você não deve manter uma referência a um objeto simulado e aplicar
thenRteturn
em um loop. Em vez disso, você deve aplicar multiplethenReturn
a umawhen()
cláusula ou aplicarthenReturn
uma vez, mas com múltiplos argumentos.Aqui está um exemplo: