<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Testcontainers Tutorial — Complete Guide to Java Integration Testing on Devops Monk</title><link>https://blog.devops-monk.com/tutorials/testcontainers/</link><description>Recent content in Testcontainers Tutorial — Complete Guide to Java Integration Testing on Devops Monk</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 23 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.devops-monk.com/tutorials/testcontainers/index.xml" rel="self" type="application/rss+xml"/><item><title>Container Reuse for Fast Feedback Loops</title><link>https://blog.devops-monk.com/tutorials/testcontainers/container-reuse/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/container-reuse/</guid><description>The singleton pattern shares a container within a single test run. Container reuse goes further — it keeps the container alive after the JVM exits and reuses it in the next test run. The first run pays the startup cost (8 seconds for Kafka). Every subsequent run skips it entirely. For a developer who runs the test suite dozens of times per day, this saves minutes of waiting.
What You&amp;rsquo;ll Learn Enabling container reuse with .</description></item><item><title>Database Migration Testing — Flyway and Liquibase with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/flyway-liquibase-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/flyway-liquibase-testing/</guid><description>Database migrations are the most dangerous code in most applications. A failed migration in production means downtime. A migration that succeeds but corrupts data is worse. Testing migrations against the actual target database — not H2, not a manual inspection — is the only way to catch migration bugs before they reach production.
This article covers testing Flyway and Liquibase migrations with Testcontainers, verifying schema correctness after migration, and testing rollback scenarios.</description></item><item><title>JUnit 5 Integration — Lifecycle and Annotations</title><link>https://blog.devops-monk.com/tutorials/testcontainers/junit5-lifecycle-annotations/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/junit5-lifecycle-annotations/</guid><description>The biggest performance factor in a Testcontainers test suite is how many times you start and stop containers. Start a PostgreSQL container once per JVM and your tests add 2 seconds to total CI time. Start it once per test method and 50 tests cost 100 seconds. Understanding Testcontainers lifecycle management is how you write fast tests without sacrificing isolation.
This article covers all the container lifecycle options in JUnit 5 — from the simplest @Container annotation to the singleton pattern that shares one container across your entire test suite.</description></item><item><title>Kafka Integration Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/kafka-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/kafka-testing/</guid><description>@EmbeddedKafka has long been the standard for Kafka testing in Spring Boot. It works, but it runs a different Kafka implementation than production — one that can accept messages and serialize records in ways that a real Kafka broker would not. KafkaContainer runs the same Confluent Kafka image your production environment uses, with the same broker configuration, same partition behavior, and same consumer group offset management. This article shows how to test Kafka producers, consumers, and dead-letter topics with a real broker.</description></item><item><title>Keycloak and OAuth2 Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/keycloak-oauth2-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/keycloak-oauth2-testing/</guid><description>Testing Spring Security with @WithMockUser and SecurityMockMvcRequestPostProcessors.jwt() verifies that your authorization annotations are wired correctly, but it does not test JWT validation, token signing algorithms, issuer URL verification, or clock skew handling. These require a real OAuth2 provider. KeycloakContainer runs a real Keycloak instance in Docker, giving you a complete OIDC server for integration tests.
What You&amp;rsquo;ll Learn KeycloakContainer setup from the community module Importing a Keycloak realm for tests Retrieving JWT access tokens programmatically Testing protected endpoints with real JWTs Testing role-based access control (RBAC) Testing token expiry and refresh flows Dependencies KeycloakContainer is not in the Testcontainers core library.</description></item><item><title>LocalStack — Testing AWS Services (S3, SQS, SNS) with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/localstack-aws-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/localstack-aws-testing/</guid><description>Testing AWS integrations against real AWS services requires IAM credentials, costs money per test run, and creates real side effects (files in S3, messages in SQS). LocalStack runs a local AWS cloud emulator in Docker — the same API, the same response format, but running locally with no AWS account required. This article covers testing S3, SQS, and SNS integrations with LocalStackContainer.
What You&amp;rsquo;ll Learn LocalStackContainer setup and @ServiceConnection Creating S3 buckets and testing file upload/download Testing SQS message producers and @SqsListener consumers Testing SNS to SQS subscriptions Creating AWS resources before tests with the AWS SDK Testing DynamoDB operations Dependencies &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;io.</description></item><item><title>MongoDB and NoSQL Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/mongodb-nosql-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/mongodb-nosql-testing/</guid><description>MongoDB&amp;rsquo;s document model introduces testing challenges that relational database tests do not have: schema flexibility (different documents can have different fields), aggregation pipelines, geospatial queries, and text search. Testing these against an embedded Flapdoodle MongoDB works for basic CRUD but breaks down for aggregation pipelines, custom index types, and MongoDB-version-specific behavior. This article covers MongoDB testing with a real MongoDB container.
What You&amp;rsquo;ll Learn MongoDBContainer setup and @ServiceConnection @DataMongoTest slice testing for repositories Testing aggregation pipelines Testing compound indexes and text indexes Querying documents with MongoTemplate Testing document validation rules Dependencies &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>MySQL Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/mysql-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/mysql-testing/</guid><description>MySQL is still the most widely deployed relational database in Java applications. Its SQL dialect, strict mode behavior, and character set handling differ from both H2 and PostgreSQL in ways that matter for real applications. This article covers MySQL testing with Testcontainers — from basic setup to MySQL-specific features and the STRICT_TRANS_TABLES mode that catches data truncation bugs H2 silently ignores.
What You&amp;rsquo;ll Learn MySQLContainer setup and configuration @ServiceConnection with MySQL MySQL strict mode and why it matters for tests Character set and collation configuration Testing MySQL-specific SQL functions MariaDB as an alternative Dependencies &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>Parallel Test Execution with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/parallel-test-execution/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/parallel-test-execution/</guid><description>A test suite with 50 integration test classes runs sequentially in 10 minutes. Configured for parallel execution across 4 threads, it completes in 3 minutes. Parallel test execution with Testcontainers requires careful data isolation — tests running simultaneously against the same database will step on each other&amp;rsquo;s data without it. This article covers JUnit 5 parallel configuration, container sharing strategies, and data isolation techniques.
What You&amp;rsquo;ll Learn JUnit 5 parallel execution configuration with junit-platform.</description></item><item><title>PostgreSQL Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/postgresql-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/postgresql-testing/</guid><description>Testing database code against H2 gives you a false sense of security. PostgreSQL has different behavior for ON CONFLICT, RETURNING, JSON operators, full-text search, and dozens of other features. A JPA query that works in H2 dialect may fail against real PostgreSQL. This article shows how to test your Spring Data JPA repositories, custom queries, and database constraints against a real PostgreSQL instance using Testcontainers.
What You&amp;rsquo;ll Learn @ServiceConnection — the Spring Boot 3.</description></item><item><title>RabbitMQ Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/rabbitmq-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/rabbitmq-testing/</guid><description>RabbitMQ&amp;rsquo;s exchange-queue model, routing keys, dead-letter exchanges, and message TTL are features that cannot be tested with mocks. The broker&amp;rsquo;s routing logic — topic exchange patterns, fanout behavior, message acknowledgment, and requeue behavior on rejection — all require a real broker. This article covers RabbitMQ integration testing with RabbitMQContainer.
What You&amp;rsquo;ll Learn RabbitMQContainer setup and @ServiceConnection Configuring exchanges, queues, and bindings for tests Testing @RabbitListener consumers with Awaitility Testing dead-letter exchange and dead-letter queue routing Testing message TTL and automatic expiry Testing acknowledgment modes Dependencies &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>Redis Testing with Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/redis-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/redis-testing/</guid><description>Redis cache testing with a real Redis instance catches behaviors that embedded or mocked alternatives cannot: TTL expiry timing, cache eviction under memory pressure, cluster failover behavior, and the exact serialization format that Redis stores data in. This article covers testing Spring Cache, Spring Session, and distributed locks against a real Redis container.
What You&amp;rsquo;ll Learn Redis GenericContainer setup and @ServiceConnection (Spring Boot 3.2+) Testing Spring Cache with @Cacheable, @CacheEvict, and @CachePut Verifying TTL expiry behavior Testing Spring Session with Redis Testing distributed locks with Redisson or Spring Integration Dependencies &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>Setting Up Testcontainers in a Java Project</title><link>https://blog.devops-monk.com/tutorials/testcontainers/setup-testcontainers-java/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/setup-testcontainers-java/</guid><description>Setting up Testcontainers takes about five minutes. The dependencies are on Maven Central, the BOM manages all version alignment, and Spring Boot 3 has first-class support that eliminates most of the configuration boilerplate. By the end of this article, you will have a Spring Boot project with Testcontainers running, a PostgreSQL container backing your first integration test, and a clear understanding of how to add any additional container module.
What You&amp;rsquo;ll Learn How the Testcontainers BOM works and why you need it Which dependencies to add for Spring Boot, PostgreSQL, and JUnit 5 How to configure Maven and Gradle for Testcontainers tests How to set up Logback so you can see container startup logs How @ServiceConnection eliminates @DynamicPropertySource boilerplate in Spring Boot 3.</description></item><item><title>Singleton Containers and Shared Base Classes</title><link>https://blog.devops-monk.com/tutorials/testcontainers/singleton-containers/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/singleton-containers/</guid><description>With 20 integration test classes, each starting its own PostgreSQL container, you pay 20 container starts at 2 seconds each — 40 seconds of pure overhead before a single assertion runs. The singleton pattern starts one container per JVM, shares it across all test classes, and cuts that 40 seconds to 2. This is the most impactful performance optimization for large Testcontainers test suites.
What You&amp;rsquo;ll Learn The singleton pattern using a static initializer block Abstract base class design for sharing containers and @DynamicPropertySource Why you must not combine @Testcontainers/@Container with the singleton pattern Spring TestContext caching — how it works and how to maximize reuse The @ImportTestcontainers approach for Spring Boot 3.</description></item><item><title>Spring Boot Testing Slices — @DataJpaTest, @WebMvcTest, and @SpringBootTest</title><link>https://blog.devops-monk.com/tutorials/testcontainers/spring-boot-testing-slices/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/spring-boot-testing-slices/</guid><description>@SpringBootTest starts the full application context — all beans, all auto-configurations, all datasources, all message listeners. That is 10–30 seconds of startup time for every test class that needs it. Spring Boot&amp;rsquo;s test slices load a subset of the application context — only the beans relevant to what you are testing. Repository tests that once took 15 seconds with @SpringBootTest take 2 seconds with @DataJpaTest. This article covers all the major test slices and how to combine them with Testcontainers.</description></item><item><title>Testcontainers in CI/CD — GitHub Actions, Docker, and Production Patterns</title><link>https://blog.devops-monk.com/tutorials/testcontainers/testcontainers-cicd/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/testcontainers-cicd/</guid><description>Testcontainers tests that run perfectly on your developer laptop can fail in CI for environmental reasons — Docker daemon availability, image pull timeouts, port conflicts, and resource limits. This final article covers production-ready CI/CD configuration for Testcontainers in GitHub Actions, GitLab CI, and Jenkins, plus Spring Boot 3.1&amp;rsquo;s development-time container support.
What You&amp;rsquo;ll Learn GitHub Actions configuration for Testcontainers (zero extra setup on ubuntu-latest) GitLab CI configuration with Docker-in-Docker Jenkins configuration with Docker socket mounting TestApplication — running your app locally with containers instead of a real database .</description></item><item><title>Understanding Wait Strategies in Testcontainers</title><link>https://blog.devops-monk.com/tutorials/testcontainers/wait-strategies/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/wait-strategies/</guid><description>A container being started does not mean it is ready to accept connections. Docker marks the container as running the moment the entrypoint process starts. PostgreSQL needs another second or two to initialize storage, bind to port 5432, and start accepting connections. If your test code tries to connect before the database is ready, you get Connection refused.
The wrong solution is Thread.sleep(5000). That is a fixed delay: too short on a slow machine, too long on a fast one.</description></item><item><title>Unit Testing vs Integration Testing vs System Testing in Java</title><link>https://blog.devops-monk.com/tutorials/testcontainers/unit-integration-system-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/unit-integration-system-testing/</guid><description>&amp;ldquo;We have 90% test coverage&amp;rdquo; means nothing if 90% of your tests are mocking away the parts that matter. A codebase full of unit tests that mock every dependency can have excellent coverage numbers while completely missing bugs that manifest when real components interact. Understanding the difference between unit tests, integration tests, and system tests — and when to use each — is the foundation of a test suite that actually finds bugs.</description></item><item><title>What Is Testcontainers and Why You Need It</title><link>https://blog.devops-monk.com/tutorials/testcontainers/what-is-testcontainers/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/what-is-testcontainers/</guid><description>Your CI pipeline goes green. You deploy to staging. The application crashes on startup because Flyway migrations fail against MySQL — but all your tests used H2. Your team has seen this before. Tests that pass on every machine, fail in production. Not because the business logic was wrong, but because the test infrastructure was fake.
This is the problem Testcontainers was built to solve.
This article covers what Testcontainers is, why traditional approaches to integration testing fall short, and how Testcontainers gives you test environments that match production — automatically, repeatably, with no shared test database to maintain.</description></item><item><title>WireMock — Testing External REST API Integrations</title><link>https://blog.devops-monk.com/tutorials/testcontainers/wiremock-testing/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://blog.devops-monk.com/tutorials/testcontainers/wiremock-testing/</guid><description>Most Spring Boot applications call external APIs — payment gateways, shipping providers, notification services, CRM systems. Testing these integrations is hard because external APIs have rate limits, authentication requirements, and a habit of being unavailable at exactly the wrong moment. WireMock runs a real HTTP server in a Docker container, accepts your requests, and returns whatever responses you configure. This article covers WireMock as a Testcontainer for testing Spring Boot REST client integrations.</description></item></channel></rss>