The Pain of Keycloak SPI Development
Developing custom Service Provider Interfaces (SPIs) for Keycloak, such as custom authenticators, often leads to a frustratingly slow and manual development cycle. Most tutorials for creating Keycloak SPIs conclude after detailing how to package the JAR and where to place it in the Keycloak server's provider directory. They stop short of showing how to effectively test these custom components. This leaves developers with a tedious feedback loop: package the SPI, copy the JAR to the Keycloak server, restart Keycloak, and then manually trigger a login flow to see if it works. Repeating this process for every small change is inefficient and prone to errors.
While the logic within an SPI might be unit-testable by extracting pure functions and mocking Keycloak's model objects using standard JUnit and Mockito, this approach doesn't validate the crucial aspect: does the SPI deploy correctly and function within a real Keycloak instance? This is where the need for integration testing with a live Keycloak environment becomes apparent.

Introducing Testcontainers for Keycloak SPIs
Testcontainers offers a powerful solution to this problem by providing a way to run Keycloak within a Docker container, managed entirely by your tests. This allows for automated integration testing of your SPIs, mimicking a production-like environment without the manual overhead. The primary benefit is the ability to test the deployment and runtime behavior of your SPIs in an isolated, reproducible, and automated manner.
The core idea is to spin up a Keycloak instance as a Docker container, deploy your custom SPI JAR to it, and then execute test cases against this running instance. This eliminates the need to manually copy JARs and restart the server. Testcontainers handles the lifecycle of the container, ensuring it's up and running before tests execute and cleaned up afterward.
Setting Up Testcontainers for Keycloak
To integrate Testcontainers into your Keycloak SPI testing strategy, you'll typically need the following dependencies in your project's build file (e.g., Maven's pom.xml or Gradle's build.gradle):
- Testcontainers core library.
- The Testcontainers module for Keycloak. If a dedicated module doesn't exist, you can use the generic Docker image functionality with a Keycloak Docker image.
- Your testing framework (e.g., JUnit 5).
Here’s a conceptual outline of the test setup:
- Define a Keycloak Container: Use Testcontainers to instantiate a Keycloak container. You can specify the desired Keycloak version and potentially pre-configure it with custom settings or modules. For instance, you might use a specific Keycloak Docker image tag.
- Mount the SPI JAR: The critical step is to make your custom SPI JAR available to the running Keycloak container. Testcontainers allows you to mount local files or directories into the container. You would mount your built SPI JAR into the appropriate Keycloak provider directory (e.g.,
/opt/keycloak/providers/). - Start the Container: The container is then started. Testcontainers ensures it's ready for use, often by waiting for Keycloak to become accessible via its HTTP endpoint.
- Deploy and Test: Once the container is running and your SPI is deployed, your test code can interact with Keycloak. This might involve making HTTP requests to Keycloak's admin or user-facing APIs to trigger authentication flows, query user data, or verify SPI-specific configurations and behaviors.

Writing Integration Tests
With the Testcontainers setup in place, you can write integration tests that verify your SPI's functionality. These tests go beyond simple unit tests by interacting with the actual Keycloak server.
Testing Custom Authenticators
For custom authenticators, a typical test scenario would involve:
- Initiating a Login Flow: Send a request to Keycloak's `/realms/{realm}/protocol/openid-connect/auth` endpoint to start an OAuth2 authorization code flow.
- Intercepting the Flow: Your test would then need to interact with the authentication SPI. This might involve making subsequent requests to the authentication endpoint that your custom authenticator expects, passing in specific parameters or headers.
- Validating SPI Logic: Assert that the authentication flow proceeds as expected, that the correct user is authenticated, or that custom attributes are set as per your SPI's logic. You can also test error conditions, such as invalid credentials or misconfigurations.
Testing Other SPI Types
The same principles apply to other SPI types:
- User Storage SPIs: Test the retrieval, creation, or update of users by interacting with Keycloak's user management APIs and verifying that your SPI correctly interfaces with the underlying user store.
- Event SPIs: Trigger events within Keycloak and verify that your custom event listener SPI receives and processes them correctly.
- Required Actions SPIs: Test the deployment and execution of custom required actions during user registration or profile updates.
The Advantages of This Approach
Adopting Testcontainers for Keycloak SPI testing offers significant advantages:
- Automation: Eliminates manual steps, allowing for continuous integration and deployment pipelines.
- Reproducibility: Ensures tests run in a consistent environment, regardless of the developer's local setup or the CI server.
- Isolation: Each test run is isolated, preventing interference between tests and providing a clean slate.
- Speed: While not as fast as pure unit tests, it's significantly faster than manual testing and complex setup procedures.
- Reliability: Reduces the chance of errors introduced by manual configuration or environment drift.
This approach shifts Keycloak SPI development from a manual, iterative process to an automated, robust testing paradigm. It addresses the gap left by most tutorials, empowering developers to build and verify their custom Keycloak extensions with confidence and efficiency. The ability to test the full deployment and runtime behavior within a containerized environment is key to developing reliable and production-ready SPIs.
