Los eventos no se activarán porque las clases de prueba no están registradas y resueltas desde el contexto de la aplicación de primavera, que es el editor del evento.
Implementé una solución para esto donde el evento se maneja en otra clase que se registra con Spring como un bean y se resuelve como parte de la prueba. No es lindo, pero después de perder la mejor parte de un día tratando de encontrar una mejor solución, estoy contento con esto por ahora.
Mi caso de uso estaba disparando un evento cuando se recibe un mensaje dentro de un consumidor de RabbitMQ. Se compone de los siguientes:
El contenedor de clase
Nota la Init() función que se llama desde la prueba de pasar en la función de devolución de llamada después de resolver desde el contenedor dentro de la prueba
public class TestEventListenerWrapper {
CountDownLatch countDownLatch;
TestEventWrapperCallbackFunction testEventWrapperCallbackFunction;
public TestEventListenerWrapper(){
}
public void Init(CountDownLatch countDownLatch, TestEventWrapperCallbackFunction testEventWrapperCallbackFunction){
this.countDownLatch = countDownLatch;
this.testEventWrapperCallbackFunction = testEventWrapperCallbackFunction;
}
@EventListener
public void onApplicationEvent(MyEventType1 event) {
testEventWrapperCallbackFunction.CallbackOnEventFired(event);
countDownLatch.countDown();
}
@EventListener
public void onApplicationEvent(MyEventType2 event) {
testEventWrapperCallbackFunction.CallbackOnEventFired(event);
countDownLatch.countDown();
}
@EventListener
public void onApplicationEvent(OnQueueMessageReceived event) {
testEventWrapperCallbackFunction.CallbackOnEventFired(event);
countDownLatch.countDown();
}
}
La interfaz de devolución de llamada
public interface TestEventWrapperCallbackFunction {
void CallbackOnEventFired(ApplicationEvent event);
}
Una clase de configuración de prueba para definir el bean al que se hace referencia en la prueba unitaria. Antes de que esto es útil, tendrá que ser resuelto desde el applicationContext y initialsed (ver paso siguiente)
@Configuration
public class TestContextConfiguration {
@Lazy
@Bean(name="testEventListenerWrapper")
public TestEventListenerWrapper testEventListenerWrapper(){
return new TestEventListenerWrapper();
}
}
Por último, la propia prueba de unidad que resuelve el grano de la applicationContext y llama a la Init() función para pasar los criterios de aserción (esto supone que ha registrado el bean como singleton, el valor predeterminado para Spring applicationContext). La función de devolución de llamada se define aquí y también pasó a Init().
@ContextConfiguration(classes= {TestContextConfiguration.class,
//..., - other config classes
//..., - other config classes
})
public class QueueListenerUnitTests
extends AbstractTestNGSpringContextTests {
private MessageProcessorManager mockedMessageProcessorManager;
private ChannelAwareMessageListener queueListener;
private OnQueueMessageReceived currentEvent;
@BeforeTest
public void Startup() throws Exception {
this.springTestContextPrepareTestInstance();
queueListener = new QueueListenerImpl(mockedMessageProcessorManager);
((QueueListenerImpl) queueListener).setApplicationEventPublisher(this.applicationContext);
currentEvent = null;
}
@Test
public void HandleMessageReceived_QueueMessageReceivedEventFires_WhenValidMessageIsReceived() throws Exception {
//Arrange
//Other arrange logic
Channel mockedRabbitmqChannel = CreateMockRabbitmqChannel();
CountDownLatch countDownLatch = new CountDownLatch(1);
TestEventWrapperCallbackFunction testEventWrapperCallbackFunction = (ev) -> CallbackOnEventFired(ev);
TestEventListenerWrapper testEventListenerWrapper = (TestEventListenerWrapper)applicationContext.getBean("testEventWrapperOnQueueMessageReceived");
testEventListenerWrapper.Init(countDownLatch, testEventWrapperCallbackFunction);
//Act
queueListener.onMessage(message, mockedRabbitmqChannel);
long awaitTimeoutInMs = 1000;
countDownLatch.await(awaitTimeoutInMs, TimeUnit.MILLISECONDS);
//Assert - assertion goes here
}
//The callback function that passes the event back here so it can be made available to the tests for assertion
private void CallbackOnEventFired(ApplicationEvent event){
currentEvent = (OnQueueMessageReceived)event;
}
}
- EDIT 1: El código de ejemplo se ha actualizado con CountDownLatch
- EDIT 2: Las afirmaciones no dejó de pruebas de lo que lo anterior se ha actualizado con un enfoque diferente **
no hay respuesta para esta pregunta –