¿Cómo puedo usar la inyección con Mockito y JUnit 5?
En JUnit4 solo puedo usar la @RunWith(MockitoJUnitRunner.class)
Anotación. ¿En JUnit5 no hay @RunWith
anotación?
¿Cómo puedo usar la inyección con Mockito y JUnit 5?
En JUnit4 solo puedo usar la @RunWith(MockitoJUnitRunner.class)
Anotación. ¿En JUnit5 no hay @RunWith
anotación?
Respuestas:
Hay diferentes formas de usar Mockito; las revisaré una por una.
Crear simulacros manualmente con Mockito::mock
trabajos independientemente de la versión de JUnit (o marco de prueba para el caso).
Usando la anotación @Mock y la llamada correspondiente a MockitoAnnotations::initMocks
para crear simulacros funciona independientemente de la versión de JUnit (o el marco de prueba para el caso, pero Java 9 podría interferir aquí, dependiendo de si el código de prueba termina en un módulo o no).
JUnit 5 tiene un modelo de extensión poderoso y Mockito publicó recientemente uno bajo el ID de grupo / artefacto org.mockito : mockito-junit-jupiter .
Puede aplicar la extensión agregando @ExtendWith(MockitoExtension.class)
a la clase de prueba y anotando campos simulados con @Mock
. De MockitoExtension
JavaDoc:
@ExtendWith(MockitoExtension.class)
public class ExampleTest {
@Mock
private List list;
@Test
public void shouldDoSomething() {
list.add(100);
}
}
La documentación de MockitoExtension describe otras formas de crear instancias de simulacros, por ejemplo, con inyección de constructor (si rpefer campos finales en clases de prueba).
JUnit 4 reglas y los corredores no funcionan en JUnit 5, por lo que el MockitoRule
y el corredor Mockito no se pueden utilizar.
@Test
necesidades debe ser público o el "paquete privado" es suficientemente bueno?
Utilice Mockito's MockitoExtension
. La extensión está contenida en un nuevo artefactomockito-junit-jupiter
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
Te permite escribir pruebas como lo harías con JUnit 4:
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private Foo foo;
@InjectMocks
private Bar bar; // constructor injection
...
}
@ExtendWith(MockitoExtension.class)
es equivalente @RunWith(MockitoJUnitRunner.class)
al JUnit4
Hay diferentes formas de hacerlo pero la forma más limpia y que además respeta la filosofía JUnit 5 es crear un org.junit.jupiter.api.extension.Extension
para Mockito.
1) Crear simulacros manualmente hace perder el beneficio de verificaciones adicionales de Mockito para asegurarse de que utiliza correctamente el marco.
2) Llamar MockitoAnnotations.initMocks(this)
a todas las clases de prueba es un código de placa de caldera que podríamos evitar.
Y hacer esta configuración en una clase abstracta tampoco es una buena solución.
Acopla todas las clases de prueba a una clase base.
Si luego necesita una nueva clase de prueba base por buenas razones, termina con una jerarquía de clases de 3 niveles. Por favor evítelo.
3) Test Rules es una especificidad de JUnit 4.
Ni siquiera pienses en eso.
Y el documentación es clara al respecto:
Sin embargo, si tiene la intención de desarrollar una nueva extensión para JUnit 5, utilice el nuevo modelo de extensión de JUnit Jupiter en lugar del modelo basado en reglas de JUnit 4.
4) Test Runner no es realmente la forma de extender el marco JUnit 5.
JUnit 5 simplificó el infierno de los Runners de JUnit 4 al proporcionar un modelo de extensión para escribir pruebas gracias a JUnit 5 Extensions.
Ni siquiera pienses en eso.
Así que favorece el org.junit.jupiter.api.extension.Extension
camino.
EDITAR: En realidad, Mockito incluye una extensión de júpiter: mockito-junit-jupiter
Entonces, muy simple de usar:
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FooTest {
...
}
Aquí hay una adición a la excelente respuesta de Jonathan.
Al agregar como dependencia el mockito-junit-jupiter
artefacto, el uso de @ExtendWith(MockitoExtension.class)
produjo la siguiente excepción a medida que se ejecuta la prueba:
java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;
El problema es que mockito-junit-jupiter
depende de dos bibliotecas independientes. Por ejemplo para mockito-junit-jupiter:2.19.0
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.19.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.1.0</version>
<scope>runtime</scope>
</dependency>
El problema fue que usé junit-jupiter-api:5.0.1
.
Entonces, como junit-jupiter-api
todavía se mueve a menudo en términos de API, asegúrese de depender de la misma versión de la junit-jupiter-api
que mockito-junit-jupiter
depende.
mockito-junit-jupiter
saca la versión adecuada de junit-jupiter-api
?
mockito-junit-jupiter:2.19.0
. Mientras que las versiones de JUnit Jupiter comienzan con 5
. mockito-junit-jupiter debería haber especificado en su identificador de artefacto las dos cosas (la versión de Mockito y la versión de JUnit Jupiter) para aclarar las cosas. Por ejemplo, mockito-junit-jupiter-5.1:2.19.0
para transmitir que la biblioteca está diseñada para JUnit Jupiter 5.1.
MockitoExtension
no parece existir en la mockito-core
versión 3.0.0.
mockito-junit-jupiter
Tienes que usar la nueva @ExtendWith
anotación.
Lamentablemente, aún no hay una extensión publicada. En github puedes ver una implementación beta para la extensión. como ejemplo de prueba de demostración .