I have created a set of custom events for my application
sealed class myEvent(open val id: Int) {
data class myBigEvent(override val id : Int) : myEvent(id)
data class myIntermediateEvent(override val id: Int): myEvent(id)
}
I have a service that has a method for listening my custom events
@Service
class MailService(
private val otherService: OtherService
) {
@EventListener(myEvent.myBigEvent::class, myEvent.myIntermediateEvent::class)
@Async
fun handleProcessEvent(event: myEvent) {
if (event.id != 10 && otherService.hasCompleted) {
sendMail(event)
}
}
The interesting point is that IntellIj annotates with the eventlistener icon next to the method defintion. When clicking on it I get redirected to all my invocations of publisher.publishEvent(myBigEvent)
or publisher.publishEvent(myIntermediateEvent)
The issue is when I try to test it. I have the following setup
@TestExecutionListeners
class myEventTest {
@Autowired
private lateinit var publisher: ApplicationEventPublisher
@Mock
private lateinit var mailService: MailService
@BeforeClass
fun start() {
publisher = ApplicationEventPublisher {}
MockitoAnnotations.initMocks(this)
}
@Test
fun `should receive cmlaProcessEvent published event`() {
val cmlaProcessEvent = JobProcessEvent.CmlaProcessSimulationProcessEvent(mlaSimulationRun)
this.publisher.publishEvent(cmlaProcessEvent)
verify(mailService, times(1)).handleProcessEvent(cmlaProcessEvent)
}
}
I get 'Wanted but not invoked' ... 'Actually, there were zero interactions with this mock.' I think my issue is with the ApplicationEventPublisher that is not sending the events to my MailService under this test context ?
CodePudding user response:
Remove @TestExecutionListeners
, since the default listeners should suffice.
If you're using Spring Boot, you should use @MockBean
instead of @Mock
.
In any case, you have to actually instruct JUnit to use Spring's testing support.
I assume that you are using JUnit 4, since I see @BeforeClass
in the example. So I'm basing the following on that assumption (and using Java syntax instead of Kotlin).
You can instruct JUnit 4 to use Spring's testing support via @RunWith(SpringRunner.class)
. Note, however, that you'll also need to specify where your ApplicationContext
configuration is.
For Spring Framework, you can do that with @ContextConfiguration
. For Spring Boot, you'll likely want to use @SpringBootTest
. Consult the documentation for testing support in Spring Framework and Spring Boot for details.
As a side note, you can also test ApplicationEvent
publication without using a mock by using Spring Framework's built-in testing support for application events.