java - test - Cómo resolver la excepción de troquelado innecesario
spring test (9)
Al mirar una parte de su seguimiento de pila, parece que está tropezando con el
dao.doSearch()
otro lugar.
Más como crear repetidamente los apéndices del mismo método.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use ''silent'' option. More info: javadoc for UnnecessaryStubbingException class.
Considere la siguiente clase de prueba, por ejemplo:
@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
@Mock
Service1 svc1Mock1;
@Mock
Service2 svc2Mock2;
@InjectMock
TestClass class;
//Assume you have many dependencies and you want to set up all the stubs
//in one place assuming that all your tests need these stubs.
//I know that any initialization code for the test can/should be in a
//@Before method. Lets assume there is another method just to create
//your stubs.
public void setUpRequiredStubs() {
when(svc1Mock1.someMethod(any(), any())).thenReturn(something));
when(svc2Mock2.someOtherMethod(any())).thenReturn(somethingElse);
}
@Test
public void methodUnderTest_StateUnderTest_ExpectedBehavior() {
// You forget that you defined the stub for svcMock1.someMethod or
//thought you could redefine it. Well you cannot. That''s going to be
//a problem and would throw your UnnecessaryStubbingException.
when(svc1Mock1.someMethod(any(),any())).thenReturn(anyThing);//ERROR!
setUpRequiredStubs();
}
}
Prefiero considerar la refactorización de sus pruebas para tropezar donde sea necesario.
Mi código es el siguiente
@RunWith(MockitoJUnitRunner.class)
public class MyClass {
private static final String code ="Test";
@Mock
private MyClassDAO dao;
@InjectMocks
private MyClassService Service = new MyClassServiceImpl();
@Test
public void testDoSearch() throws Exception {
final String METHOD_NAME = logger.getName().concat(".testDoSearchEcRcfInspections()");
CriteriaDTO dto = new CriteriaDTO();
dto.setCode(code);
inspectionService.searchEcRcfInspections(dto);
List<SearchCriteriaDTO> summaryList = new ArrayList<SearchCriteriaDTO>();
inspectionsSummaryList.add(dto);
when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
verify(dao).doSearchInspections(dto);
}
}
Me estoy poniendo por debajo de la excepción
org.mockito.exceptions.misusing.UnnecessaryStubbingException: Unnecessary stubbings detected in test class: Test Clean & maintainable test code requires zero unnecessary code. Following stubbings are unnecessary (click to navigate to relevant line of code): 1. -> at service.Test.testDoSearch(Test.java:72) Please remove unnecessary stubbings or use ''silent'' option. More info: javadoc for UnnecessaryStubbingException class. at org.mockito.internal.exceptions.Reporter.formatUnncessaryStubbingException(Reporter.java:838) at org.mockito.internal.junit.UnnecessaryStubbingsReporter.validateUnusedStubs(UnnecessaryStubbingsReporter.java:34) at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:49) at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:103) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Por favor, ayúdame a resolver
Al principio debes verificar tu lógica de prueba. Por lo general, hay 3 casos. Primero, se está burlando del método incorrecto (cometió un error tipográfico o alguien cambió el código probado para que el método burlado ya no se use). En segundo lugar, su prueba falla antes de que se llame a este método. En tercer lugar, su lógica se equivoca si / cambia de rama en algún lugar del código, por lo que no se llama al método burlado.
Si este es el primer caso, siempre desea cambiar el método simulado por el utilizado en el código. Con el segundo y el tercero depende. Por lo general, solo debe eliminar este simulacro si no tiene uso. Pero a veces hay ciertos casos en las pruebas parametrizadas, que deberían tomar este camino diferente o fallar antes. Luego puede dividir esta prueba en dos o más, pero eso no siempre es atractivo. 3 métodos de prueba con posiblemente 3 proveedores de argumentos pueden hacer que la prueba parezca ilegible. En ese caso para JUnit 4, silencia esta excepción con
@RunWith(MockitoJUnitRunner.Silent.class)
anotación o si está utilizando el enfoque de regla
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);
o (el mismo comportamiento)
@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();
Para las pruebas JUnit 5, puede silenciar esta excepción utilizando la anotación proporcionada en el
mockito-junit-jupiter
.
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}
En el caso de un proyecto grande, es difícil solucionar cada una de estas excepciones.
Al mismo tiempo, no se recomienda usar
Silent
.
He escrito un script para eliminar todos los trozos innecesarios dada una lista de ellos.
https://gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b
Solo necesitamos copiar y pegar la salida de
mvn
y escribir la lista de estas excepciones usando regex y dejar que el script se encargue del resto.
Para mí, ni las
@Rule
ni
@RunWith(MockitoJUnitRunner.Silent.class)
funcionaron.
Fue un proyecto heredado donde actualizamos a mockito-core 2.23.0.
Podríamos deshacernos de la
UnnecessaryStubbingException
usando:
Mockito.lenient().when(mockedService.getUserById(any())).thenReturn(new User());
en vez de:
when(mockedService.getUserById(any())).thenReturn(new User());
No es necesario decir que debería mirar el código de prueba, pero necesitamos compilar todo y ejecutar las pruebas en primer lugar;)
Reemplace
@RunWith(MockitoJUnitRunner.class)
con
@RunWith(MockitoJUnitRunner.Silent.class)
.
Si estás usando este estilo en su lugar:
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
reemplazarlo con:
@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();
Tuve
UnnecessaryStubbingException
cuando intenté usar los métodos
when
en un objeto Spy.
Mockito.lenient()
silenció la excepción pero los resultados de la prueba no fueron correctos.
En el caso de los objetos Spy, uno tiene que llamar a los métodos directamente.
@ExtendWith(MockitoExtension.class) @RunWith(JUnitPlatform.class) class ArithmTest { @Spy private Arithm arithm; @Test void testAddition() { int res = arithm.add(2, 5); // doReturn(7).when(arithm).add(2, 5); assertEquals(res, 7); } }
El silencio no es una solución. Necesitas arreglar tu simulacro en tu prueba. Ver documentación oficial here .
Los apéndices innecesarios son llamadas de método apurado que nunca se realizaron durante la ejecución de la prueba (véase también MockitoHint), por ejemplo:
//code under test:
...
String result = translator.translate("one")
...
//test:
...
when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
...
Observe que uno de los métodos apagados nunca se realizó en el código bajo prueba, durante la ejecución de la prueba. El trozo perdido podría ser un descuido del desarrollador, el artefacto de copiar y pegar o el efecto de no comprender la prueba / código. De cualquier manera, el desarrollador termina con un código de prueba innecesario. Para mantener la base de código limpia y mantenible, es necesario eliminar el código innecesario. De lo contrario, las pruebas son más difíciles de leer y razonar.
Para obtener más información sobre la detección de trozos no utilizados, consulte MockitoHint.
when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
verify(dao).doSearchInspections(dto);
when
aquí configura tu simulacro para hacer algo.
Sin embargo, ya no usa este simulacro después de esta línea (aparte de hacer una
verify
).
Mockito te advierte que la línea
when
tiene sentido.
¿Quizás cometiste un error lógico?