Gli eventi non vengono attivati perché le classi di test non sono registrate e risolte dal contesto dell'applicazione di primavera, che è l'editore dell'evento.
Ho implementato una soluzione alternativa per questo in cui l'evento viene gestito in un'altra classe registrata con Spring come bean e risolta come parte del test. Non è bello, ma dopo aver sprecato la parte migliore di un giorno cercando di trovare una soluzione migliore, sono contento di questo per ora.
Il mio caso di utilizzo ha generato un evento quando viene ricevuto un messaggio all'interno di un utente RabbitMQ. Si compone delle seguenti operazioni:
L'involucro classe
Nota la Init) funzione (che viene chiamata dal test di passare nella funzione di callback dopo aver risolto dal contenitore all'interno del test
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();
}
}
L'interfaccia di callback
public interface TestEventWrapperCallbackFunction {
void CallbackOnEventFired(ApplicationEvent event);
}
Una classe di configurazione di prova per definire il bean a cui viene fatto riferimento nel test dell'unità. Prima di questo è utile, dovrà essere risolto dal applicationContext e initialsed (vedi passo successivo)
@Configuration
public class TestContextConfiguration {
@Lazy
@Bean(name="testEventListenerWrapper")
public TestEventListenerWrapper testEventListenerWrapper(){
return new TestEventListenerWrapper();
}
}
Infine, la prova stessa unità che risolve il fagiolo dalla applicationContext e chiama il Init() Funzione per passare i criteri di asserzione (questo presuppone che tu abbia registrato il bean come un singleton - il valore predefinito per Spring applicationContext). La funzione di callback è qui definita e anche passata 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: Il codice di esempio è stato aggiornato con CountDownLatch
- EDIT 2: asserzioni non sicuro test in modo che il sopra è stato aggiornato con un approccio diverso **
perciò non ci sono risposta per questa domanda –