# Unit testing event listeners?

**URL:** <https://forum.keycloak.org/t/unit-testing-event-listeners/11763>\
**Category:** Extending the server\
**Created:** [October 27, 2021, 7:11pm UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763 "2021-10-27T19:11:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [October 27, 2021, 7:11pm UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763/1 "2021-10-27T19:11:51Z")

</div>

Does anyone have any recommendations on properly unit testing an `EventListenerProvider` implementation? I suppose this would actually be more functional/integration testing, as it would ideally involve bringing up a Keycloak instance, installing/activating the listener, and performing some actions, and then validating that an event had been received by the listener.

I’ve been thinking about either using the `org.keycloak.testsuite.KeycloakServer` in junit or the `testcontainers` approach. I wanted to see if anyone here had a recommendation or template.

Thank you!

---

<div class="post-metadata">

**Author:** ![dasniko](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/dasniko/32/2969_2.png) [@dasniko](https://forum.keycloak.org/u/dasniko)\
**Post date:** [October 27, 2021, 7:17pm UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763/2 "2021-10-27T19:17:17Z")

</div>

You already know my `testcontainers-keycloak` project?

> **[GitHub - dasniko/testcontainers-keycloak: A Testcontainer implementation for...](https://github.com/dasniko/testcontainers-keycloak)**
>
> A Testcontainer implementation for Keycloak IAM & SSO. - GitHub - dasniko/testcontainers-keycloak: A Testcontainer implementation for Keycloak IAM & SSO.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [October 27, 2021, 7:32pm UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763/3 "2021-10-27T19:32:49Z")

</div>

I didn’t know about it. This is awesome. Thank you @dasniko !

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [October 28, 2021, 9:00am UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763/4 "2021-10-28T09:00:07Z")

</div>

Also, I tried another approach that uses the `org.keycloak.testsuite.KeycloakServer`. The downside is that because `keycloak-testsuite-utils` isn’t in Maven Central, you have to build it yourself in order to use this method. The upside is that it works with JUnit4, which I had the requirement of sticking to. This also ran much faster than the testcontainers approach, but is less flexible in features, control, and similarity to an actual production environment.

This is how to use it in JUnit4:

```java
  @ClassRule public static KeycloakSuite server = KeycloakSuite.SERVER;

  @BeforeClass
  public static void commonSetup() {
    Keycloak keycloak = server.client();
    //do setup here that is common to all tests in this class
  }

  @Test
  public void exampleTest() {
    Keycloak keycloak = server.client();
    RealmRepresentation realm = keycloak.realm("master").toRepresentation();
    assertThat(realm.getId(), is("master"));
  }

```

Full code here:

> <https://gist.github.com/xgp/a23f3357ef977c70f6dc6e74a3b3f2e0>

---

<div class="post-metadata">

**Author:** ![semangard](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/semangard/32/1922_2.png) [@semangard](https://forum.keycloak.org/u/semangard)\
**Post date:** [December 15, 2021, 5:53am UTC](https://forum.keycloak.org/t/unit-testing-event-listeners/11763/5 "2021-12-15T05:53:07Z")

</div>

You can also do JUnit tests with mocks (e.g. Mockito)

```auto

@ExtendWith(MockitoExtension.class)
@TestMethodOrder(OrderAnnotation.class)
final class HUGListenerTests extends AbstractTests {

	@Mock(answer = Answers.RETURNS_DEEP_STUBS)
	private Event event;

	@Mock(answer = Answers.RETURNS_DEEP_STUBS)
	KeycloakSession session;

	@InjectMocks
	@Spy
	private HUGListener listener = new HUGListener(session);

	@Captor
	private ArgumentCaptor<String> stringCaptor;

	@BeforeAll
	private static void beforeAll() throws Exception {
	}

	@AfterAll
	private static void afterAll() throws IOException {
	}

	HUGListenerTests() throws Exception {
		logger = Logger.getLogger(HUGListenerTests.class);
	}

	@Test
	@DisplayName("Supported event KO")
	@Order(1)
	void onSupportedEvent_KO(TestInfo testInfo) throws Exception {
		logInfos(testInfo);

		when(event.getType()).thenReturn(EventType.RESTART_AUTHENTICATION);

		listener.onEvent(event);

		verify(listener, times(1)).onNotSupportedEvent(event);

		logSep();
	}

	@Test
	@DisplayName("Login event OK")
	@Order(2)
	void onLoginEvent_OK(TestInfo testInfo) throws Exception {
		logInfos(testInfo);

		when(event.getType()).thenReturn((EventType) HUGListener.USER_EVENT_TYPES_4_LOGIN_HISTORY.toArray()[0]);
		when(event.getRealmId()).thenReturn("realmId");
		when(event.getUserId()).thenReturn("userId");
		RealmModel realm = session.realms().getRealm(event.getRealmId());
		UserModel user = session.users().getUserById(event.getUserId(), realm);
		when(user.getId()).thenReturn("userId");
		when(user.getAttribute(UserUtil.USER_ATTR_LOGIN_HISTORY)).thenReturn(List.of(LoginHistory.testDataAsJson()));

		listener.onEvent(event);

		verify(listener, times(1)).onLoginEvent(event, user);

		logSep();
	}

```
