viral odio moderno libro hoy futbol eterno java unit-testing testing mocking mockito

java - odio - Método final de burla



video viral (6)

De las preguntas frecuentes de Mockito :

Cuáles son las limitaciones de Mockito

  • No se puede burlar de los métodos finales: su comportamiento real se ejecuta sin excepción. Mockito no puede advertirte sobre burlarse de los métodos finales, así que ten cuidado.

Necesito simular una clase con el método final usando mockito. He escrito algo como esto

@Test public void test() { B b = mock(B.class); doReturn("bar called").when(b).bar(); assertEquals("must be /"overrided/"", "bar called", b.bar()); //bla-bla } class B { public final String bar() { return "fail"; } }

Pero falla. Probé un poco de "pirateo" y funciona.

@Test public void hackTest() { class NewB extends B { public String barForTest() { return bar(); } } NewB b = mock(NewB.class); doReturn("bar called").when(b).barForTest(); assertEquals("must be /"overrided/"", "bar called", b.barForTest()); }

Funciona, pero "huele".

Entonces, ¿dónde está el camino correcto?

Gracias.



No hay soporte para burlarse de los métodos finales en Mockito.

Como comentó Jon Skeet, debería buscar una forma de evitar la dependencia del método final. Dicho esto, hay algunas formas de salir de la manipulación de bytecode (por ejemplo, con PowerMock)

Una comparación entre Mockito y PowerMock explicará las cosas en detalle.


Puedes usar Powermock junto con Mockito, entonces no necesitas subclasificar B.class. Solo agregue esto a la parte superior de su clase de prueba

@RunWith(PowerMockRunner.class) @PrepareForTest(B.class)

@PrepareForTest instruye a Powermock a instrumentar a B.class para que los métodos finales y estáticos se puedan burlar. Una desventaja de este enfoque es que debe usar PowerMockRunner que excluye el uso de otros corredores de prueba como el corrector de prueba de Spring.


Solo hice lo mismo. Mi caso fue que quería asegurarme de que el método no "Causa" un error, pero dado que es un método catch / log / return, no pude probarlo directamente sin modificar la clase.

Quería simplemente burlarme del registrador que pasé, pero algo sobre burlarse de la interfaz "Log" no parecía funcionar y burlarse de una clase como "SimpleLog" no funcionaba porque esos métodos son definitivos.

Terminé creando una clase interna anónima que ampliaba SimpleLog que sobrepasaba el método de "nivel de registro (nivel, cadena, error)" de nivel base al que todos los demás delegan, y luego simplemente esperaban una llamada con un "nivel" de 5.

En general, extender una clase por comportamiento no es realmente una mala idea, podría ser preferible a la burla de todos modos si no es demasiado complicado.


Suponiendo que la clase B es la siguiente:

class B { private String barValue; public final String bar() { return barValue; } public void final setBar(String barValue) { this.barValue = barValue; } }

Hay una forma mejor de hacerlo sin usar el marco PowerMockito. Puede crear un SPY para su clase y puede burlarse de su método final. Debajo está la manera de hacerlo:

@Test public void test() { B b = new B(); b.setBar("bar called") //This should the expected output:final_method_bar() B spyB = Mockito.spy(b); assertEquals("bar called", spyB.bar()); }