
Unit Test Application Events
Unit-test Spring ApplicationEvent publishers and listeners with JUnit 5 and Mockito without spinning up the full Spring context.
Overview
Unit Test Application Events is an agent skill for the Ship phase that teaches Spring Boot developers how to unit-test ApplicationEvent publishing and @EventListener behavior with JUnit 5 and Mockito.
Install
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill unit-test-application-eventsWhat is this skill?
- Mock ApplicationEventPublisher with Mockito in service unit tests
- Capture and assert event payloads with ArgumentCaptor
- Invoke @EventListener methods directly against mocked dependencies
- Patterns for async @Async + @EventListener handling with Awaitility or timing
- JUnit 5 + AssertJ setup aligned with spring-boot-starter test stack
Adoption & trust: 1.1k installs on skills.sh; 271 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You publish or handle Spring application events but lack fast unit tests that prove the right payload was fired and listeners ran without a full context boot.
Who is it for?
Indie builders on Spring Boot who use domain events and want Mockito-based unit tests in CI without @SpringBootTest for every case.
Skip if: Teams only needing integration tests with Testcontainers, non-Spring stacks, or frontend-only work with no Java backend.
When should I use this skill?
Writing tests for event listeners, mocking application events, or verifying events were published in Spring Boot services.
What do I get? / Deliverables
You get repeatable unit-test patterns with mocked publishers, captured events, and verified listener side effects ready to gate merges and releases.
- Unit tests for publishers and listeners
- ArgumentCaptor assertions on event payloads
Recommended Skills
Journey fit
How it compares
Use for focused event unit tests instead of heavier @SpringBootTest slices when you only need publisher and listener contracts.
Common Questions / FAQ
Who is unit-test-application-events for?
Solo and small-team Java developers using Spring Boot event-driven patterns who write JUnit 5 tests and want Mockito-friendly recipes without always loading the full context.
When should I use unit-test-application-events?
Use it in Ship/testing when adding tests for event publishers, @EventListener methods, async handlers, or when you must assert ApplicationEventPublisher was called with the correct payload during a service refactor.
Is unit-test-application-events safe to install?
It is procedural test documentation with allowed-tools Read, Write, Bash, Glob, Grep; review the Security Audits panel on this Prism page before trusting third-party skill sources.
SKILL.md
READMESKILL.md - Unit Test Application Events
# Unit Testing Application Events ## Overview Provides actionable patterns for testing Spring `ApplicationEvent` publishers and `@EventListener` consumers using JUnit 5 and Mockito — without booting the full Spring context. ## When to Use - Writing unit tests for event publishers or listeners - Verifying that an event was published with correct payload - Testing `@EventListener` method invocation and side effects - Testing event propagation through multiple listeners - Validating async event handling (`@Async` + `@EventListener`) - Mocking `ApplicationEventPublisher` in service tests ## Instructions 1. **Add test dependencies**: `spring-boot-starter`, JUnit 5, Mockito, AssertJ 2. **Mock ApplicationEventPublisher**: use `@Mock` on the publisher field in the service under test 3. **Capture events with ArgumentCaptor**: `ArgumentCaptor.forClass(EventType.class)` to inspect published payload 4. **Verify listener side effects**: invoke listener directly against mocked dependencies 5. **Test async handlers**: use `Thread.sleep()` or Awaitility — then assert the async operation was called 6. **Add validation checkpoints**: - After capturing an event, confirm `eventCaptor.getValue()` is not null before asserting fields - If the listener is not invoked, verify `publishEvent()` was called with the correct event type - If async assertions fail, increase wait time and check the executor pool is not saturated 7. **Cover error scenarios**: assert listeners handle exceptions gracefully ## Examples ### Maven ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> ``` ### Gradle ```kotlin dependencies { implementation("org.springframework.boot:spring-boot-starter") testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.mockito:mockito-core") testImplementation("org.assertj:assertj-core") } ``` ### Custom Event and Publisher Test ```java public class UserCreatedEvent extends ApplicationEvent { private final User user; public UserCreatedEvent(Object source, User user) { super(source); this.user = user; } public User getUser() { return user; } } @Service public class UserService { private final ApplicationEventPublisher eventPublisher; private final UserRepository userRepository; public UserService(ApplicationEventPublisher eventPublisher, UserRepository userRepository) { this.eventPublisher = eventPublisher; this.userRepository = userRepository; } public User createUser(String name, String email) { User savedUser = userRepository.save(new User(name, email)); eventPublisher.publishEvent(new UserCreatedEvent(this, savedUser)); return savedUser; } } ``` ### Unit Test for Event Publishing ```java @ExtendWith(MockitoExtension.class) class UserServiceEventTest { @Mock private ApplicationEventPublisher eventPublisher; @Mock private UserRepository userRepository; @InjectMocks private UserService userService; @Test void shouldPublishUserCreatedEvent() { User newUser = new User(1L, "Alice", "alice@example.com"); when(userRepository.save(any(User.class))).the