Soy un novato en desarrollo y en pruebas unitarias en particular. Supongo que mi requisito es bastante simple, pero estoy ansioso por saber qué piensan los demás sobre esto.
Supongamos que tengo dos clases así:
public class First {
Second second ;
public First(){
second = new Second();
}
public String doSecond(){
return second.doSecond();
}
}
class Second {
public String doSecond(){
return "Do Something";
}
}
Digamos que estoy escribiendo prueba unitaria para probar el First.doSecond()
método. Sin embargo, supongamos que quiero burlarme de la Second.doSecond()
clase así. Estoy usando Mockito para hacer esto.
public void testFirst(){
Second sec = mock(Second.class);
when(sec.doSecond()).thenReturn("Stubbed Second");
First first = new First();
assertEquals("Stubbed Second", first.doSecond());
}
Estoy viendo que la burla no tiene efecto y la afirmación falla. ¿No hay forma de burlarse de las variables miembro de una clase que quiero probar? ?
Esto no es posible si no puede cambiar su código. Pero me gusta la inyección de dependencia y Mockito lo admite:
Su prueba:
Esto es muy lindo y fácil.
fuente
Si observa detenidamente su código, verá que la
second
propiedad en su prueba sigue siendo una instanciaSecond
, no un simulacro (no pasa el simulacrofirst
en su código).La forma más sencilla sería crear un setter
second
enFirst
clase y pasarle el simulacro explícitamente.Me gusta esto:
Otra sería pasar una
Second
instancia comoFirst
parámetro constructor.Si no puede modificar el código, creo que la única opción sería usar la reflexión:
Pero probablemente pueda, ya que es raro hacer pruebas en el código que no controla (aunque uno puede imaginar un escenario en el que tiene que probar una biblioteca externa porque su autor no lo hizo :))
fuente
@Mock
y anotar Primero con@InjectMocks
e instanciar Primero en el inicializador. Mockito automáticamente hará lo mejor para encontrar un lugar para inyectar el segundo simulacro en la primera instancia, incluida la configuración de campos privados que coincidan con el tipo.@Mock
fue alrededor de 1.5 (tal vez antes, no estoy seguro). 1.8.3 introducido@InjectMocks
, así como@Spy
y@Captor
.Si no puede cambiar la variable miembro, al revés, use powerMockit y llame
Ahora el problema es que CUALQUIER llamada al nuevo Segundo devolverá la misma instancia simulada. Pero en su caso simple esto funcionará.
fuente
Tuve el mismo problema donde no se estableció un valor privado porque Mockito no llama a superconstructores. Así es como aumento la burla con la reflexión.
Primero, creé una clase TestUtils que contiene muchas utilidades útiles, incluidos estos métodos de reflexión. El acceso a la reflexión es un poco difícil de implementar cada vez. Creé estos métodos para probar el código en proyectos que, por una razón u otra, no tenían un paquete de simulación y no me invitaron a incluirlo.
Entonces puedo probar la clase con una variable privada como esta. Esto es útil para burlarse de los árboles profundos de la clase que tampoco tienes control.
Modifiqué mi código de mi proyecto real aquí, en la página. Podría haber un problema de compilación o dos. Creo que entiendes la idea general. Siéntase libre de tomar el código y usarlo si lo encuentra útil.
fuente
Muchos otros ya te han aconsejado que reconsideres tu código para hacerlo más comprobable, un buen consejo y, por lo general, más simple de lo que voy a sugerir.
Si no puede cambiar el código para hacerlo más comprobable, PowerMock: https://code.google.com/p/powermock/
PowerMock extiende Mockito (para que no tenga que aprender un nuevo marco simulado), proporcionando funcionalidad adicional. Esto incluye la posibilidad de que un constructor devuelva un simulacro. Potente, pero un poco complicado, así que úsalo juiciosamente.
Utiliza un corredor simulado diferente. Y debe preparar la clase que va a invocar al constructor. (Tenga en cuenta que este es un problema común: prepare la clase que llama al constructor, no la clase construida)
Luego, en su configuración de prueba, puede usar el método whenNew para que el constructor devuelva un simulacro
fuente
Sí, esto se puede hacer, como muestra la siguiente prueba (escrito con la API de burla de JMockit, que desarrollo):
Con Mockito, sin embargo, tal prueba no se puede escribir. Esto se debe a la forma en que se implementa la burla en Mockito, donde se crea una subclase de la clase a burlarse; solo las instancias de esta subclase "simulada" pueden tener un comportamiento simulado, por lo que debe hacer que el código probado las use en lugar de cualquier otra instancia.
fuente
Si desea una alternativa a ReflectionTestUtils de Spring en mockito, use
fuente