method - variables object java
Burlándose de una variable privada que se supone que existe (1)
Después de buscar mucho más y observar todas las opciones que Mockito / Powermock tenía para ofrecer, encontré la solución (que compartiré en caso de que otros se topen con este mismo problema).
Cuando tiene variables de miembros privados que nunca se inicializan (y se supone que se crearon en otros lugares), puede usar la anotación @InjectMocks
para "inyectar" los Mocks que desea en su clase que está probando.
- Agregue una variable en su clase de prueba para la clase que está probando y
@InjectMocks
la anotación@InjectMocks
(org.Mockito.InjectMocks). - Use
@Mock
anotaciones de@Mock
para configurar los@Mock
que desea inyectar. Use la@Mock (name = "privateVariableNameHere")
para asignar el objeto Mock a la variable privada dentro de su clase que está probando. - Ya sea en una función de configuración o antes de llamar a su clase, inicialice los simulacros. La forma más fácil que he encontrado es usar un método de "configuración" con la anotación
@Before
. Entonces, ahí dentro, llame aMockitoAnnotations.initMocks(this);
para inicializar rápidamente cualquier cosa con la anotación@Mock
. - Defina su funcionalidad de simulacro en su método de prueba (antes de llamar al método que está probando).
- Usando el objeto
@InjectMock
, llame al método que está probando ... los simulacros DEBERÍAN estar conectados y funcionando como se definió en los pasos anteriores.
Así que para la clase de ejemplo que uso anteriormente, el código para probar / simular haría que Connection
devuelto como un simulacro con el que puede hacer cualquier cosa. Basado en el ejemplo anterior en mi pregunta, este es el aspecto del código:
@RunWith(PowerMockRunner.class)
@PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
@Mock (name = "queueFactory") //same name as private var.
QueueConnectionFactory queueFactoryMock;
@Mock
Connection connectionMock; //the object we want returned
@InjectMocks
Example exampleTester; //the class to test
@Before
public void setup(){
MockitoAnnotations.initMocks(this); // initialize all the @Mock objects
// Setup other Static Mocks
}
@Test
public void testTestMe(){
//Mock your objects like other "normally" mocked objects
PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
//...Mock ConnectionMock functionality...
exampleTester.testMe();
}
}
¿Cómo puede obtener un objeto simulado en tiempo de ejecución cuando no se crea / inicializa en la clase que está probando, no es estático (patrón de singleton), o no tiene algún tipo de constructor de prueba para conectar?
En una clase para la que estoy escribiendo algunas pruebas de unidad, me he encontrado con un escenario que aún no he encontrado / resuelto. Tengo un recurso JMS (un QueueConnectionFactory
para referencia, pero no debería importar), que es una variable privada de la clase que estoy probando. Dado que tiene la anotación javax.annotation.Resource
, en tiempo de ejecución se supone que está disponible. Durante la prueba, no lo es, lo que crea la necesidad de burlarse de este objeto.
No es una clase estática y no se está utilizando de forma estática, si lo fuera, podría simularme fácilmente utilizando los diversos métodos de simulación estática que he encontrado. Dado que el recurso nunca se crea localmente (en un constructor o incluso en un constructor de prueba), no tengo forma de pasar un objeto simulado de modo que, en el tiempo de ejecución de la prueba, se utilice el simulacro en lugar del objeto real. ¿Cómo puedo simular este recurso para que cuando se ejecute la prueba, se usará en lugar del objeto @Resource
privado en la clase que estoy probando?
Para referencia, el código está llamando a createConnection()
en QueueConnectionFactory
que está lanzando una excepción de puntero nulo ya que Factory no se ha inicializado / simulado.
@Stateless
public class Example{
@Resource(name = "jms/exampleQCF")
private QueueConnectionFactory queueFactory;
...
public void testMe(){
Connection connection = queueFactory.createConnection();
...
}
}