Introduction

The @DataMongoTest annotation in Spring Boot is designed for isolated testing of MongoDB repositories. By default, it configures an embedded MongoDB (Flapdoodle) for testing. However, in real-world scenarios, we might need to test against a real MongoDB instance without installing it locally.
This is where Testcontainers comes in.
What is Testcontainers?
Testcontainers is a Java library that allows running lightweight, disposable containers for databases, message queues, and other dependencies. It is particularly useful for integration testing as it provides:
Real database testing without requiring local installation.
Fresh database instances for each test execution.
Automatic cleanup of containers after tests.
Consistent testing environments across different machines.
Project Setup
To get started, create a Spring Boot project with the following dependencies:
- Spring Boot Starter Data MongoDB – For working with MongoDB.
- Spring Boot Starter Test – Provides JUnit, AssertJ, and Mockito.
- Testcontainers MongoDB – Runs MongoDB in a container.

Spring Boot Testing Libraries
The spring-boot-starter-test dependency provides several useful testing tools:
- JUnit – The core testing framework.
- Spring Boot Test – Provides utilities for integration testing.
- AssertJ – Fluent assertion library.
- Mockito – A mocking framework.
- Testcontainers – Allows running a real MongoDB database in a container.
Implementation
1. pom.xml Configuration
To use Testcontainers with MongoDB, add the necessary dependencies to pom.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<relativePath/> <!-- lookup parent from repository -->
<groupId>tech.devblueprint</groupId>
<artifactId>datamongodb-testcontainers-spring-boot-testing-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>datamongodb-testcontainers-spring-boot-testing-example</name>
<description>Demo project for Spring Boot</description>
<java.version>17</java.version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<groupId>org.testcontainers</groupId>
<artifactId>mongodb</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>tech.devblueprint</groupId>
<artifactId>datamongodb-testcontainers-spring-boot-testing-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>datamongodb-testcontainers-spring-boot-testing-example</name>
<description>Demo project for Spring Boot</description>
<url/>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mongodb</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>tech.devblueprint</groupId>
<artifactId>datamongodb-testcontainers-spring-boot-testing-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>datamongodb-testcontainers-spring-boot-testing-example</name>
<description>Demo project for Spring Boot</description>
<url/>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mongodb</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Key Dependencies Explained:
- spring-boot-starter-data-mongodb – Enables MongoDB support.
- spring-boot-starter-test – Includes essential testing libraries.
- spring-boot-testcontainers – Enables Testcontainers integration with Spring Boot.
- org.testcontainers:mongodb – Runs MongoDB in a container.
- org.testcontainers:junit-jupiter – Integrates JUnit 5 with Testcontainers.
2. Configuring MongoDB Testcontainer
By default, @DataMongoTest starts an embedded MongoDB (Flapdoodle). To use a MongoDB container, we need to:
- Start a MongoDB Testcontainer in the test class.
- Dynamically provide the MongoDB URI to Spring Boot.
3. Document Definition
File: src/main/java/…/document/Device.java
package tech.devblueprint.datamongodb_spring_boot_testing_example.document;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "devices")
private String manufacturer;
// Parameterized constructor
public Device(String id, String name, String type, String manufacturer) {
this.manufacturer = manufacturer;
// Getter and Setter for id
public void setId(String id) {
// Getter and Setter for name
public String getName() {
public void setName(String name) {
// Getter and Setter for type
public String getType() {
public void setType(String type) {
// Getter and Setter for manufacturer
public String getManufacturer() {
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
package tech.devblueprint.datamongodb_spring_boot_testing_example.document;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "devices")
public class Device {
@Id
private String id;
private String name;
private String type;
private String manufacturer;
// Default constructor
public Device() {
}
// Parameterized constructor
public Device(String id, String name, String type, String manufacturer) {
this.id = id;
this.name = name;
this.type = type;
this.manufacturer = manufacturer;
}
// Getter and Setter for id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// Getter and Setter for name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// Getter and Setter for type
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// Getter and Setter for manufacturer
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
}
package tech.devblueprint.datamongodb_spring_boot_testing_example.document;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "devices")
public class Device {
@Id
private String id;
private String name;
private String type;
private String manufacturer;
// Default constructor
public Device() {
}
// Parameterized constructor
public Device(String id, String name, String type, String manufacturer) {
this.id = id;
this.name = name;
this.type = type;
this.manufacturer = manufacturer;
}
// Getter and Setter for id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// Getter and Setter for name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// Getter and Setter for type
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// Getter and Setter for manufacturer
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
}
4. Repository Interface
File: src/main/java/…/repository/DeviceRepository.java
package tech.devblueprint.datamongodb_spring_boot_testing_example.repository;
import tech.devblueprint.datamongodb_spring_boot_testing_example.document.Device;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.Optional;
public interface DeviceRepository extends MongoRepository<Device, String> {
// Find a device by its name
Optional<Device> findByName(String name);
package tech.devblueprint.datamongodb_spring_boot_testing_example.repository;
import tech.devblueprint.datamongodb_spring_boot_testing_example.document.Device;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.Optional;
public interface DeviceRepository extends MongoRepository<Device, String> {
// Find a device by its name
Optional<Device> findByName(String name);
package tech.devblueprint.datamongodb_spring_boot_testing_example.repository;
import tech.devblueprint.datamongodb_spring_boot_testing_example.document.Device;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.Optional;
public interface DeviceRepository extends MongoRepository<Device, String> {
// Find a device by its name
Optional<Device> findByName(String name);
Writing Tests with Testcontainers
Using a MongoDB Container in Tests
With @DataMongoTest, we can start a MongoDB container and register its connection details dynamically.
File: src/test/java/…/repository/DeviceRepositoryTestContainersTest.java
package tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.document.Device;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.repository.DeviceRepository;
import static org.assertj.core.api.Assertions.assertThat;
public class DeviceRepositoryTestContainersTest {
// Start a MongoDB container with the latest image
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:latest");
// Dynamically set the Spring property for MongoDB URI
static void setProperties(DynamicPropertyRegistry registry) {
// This provides the connection string to Spring Boot
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
private DeviceRepository deviceRepository;
// Clean up database and insert test data
deviceRepository.deleteAll();
Device device = new Device("20", "TCDevice", "Controller", "TCManufacturer");
deviceRepository.save(device);
void findByName_ReturnsDevice() {
// Test retrieval of device by name from MongoDB container
Device device = deviceRepository.findByName("TCDevice").orElse(null);
assertThat(device).isNotNull();
assertThat(device.getType()).isEqualTo("Controller");
assertThat(device.getManufacturer()).isEqualTo("TCManufacturer");
package tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.document.Device;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.repository.DeviceRepository;
import static org.assertj.core.api.Assertions.assertThat;
@Testcontainers
@DataMongoTest
public class DeviceRepositoryTestContainersTest {
// Start a MongoDB container with the latest image
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:latest");
// Dynamically set the Spring property for MongoDB URI
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
// This provides the connection string to Spring Boot
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
}
@Autowired
private DeviceRepository deviceRepository;
@BeforeEach
void setUp() {
// Clean up database and insert test data
deviceRepository.deleteAll();
Device device = new Device("20", "TCDevice", "Controller", "TCManufacturer");
deviceRepository.save(device);
}
@Test
void findByName_ReturnsDevice() {
// Test retrieval of device by name from MongoDB container
Device device = deviceRepository.findByName("TCDevice").orElse(null);
assertThat(device).isNotNull();
assertThat(device.getType()).isEqualTo("Controller");
assertThat(device.getManufacturer()).isEqualTo("TCManufacturer");
}
}
package tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.document.Device;
import tech.devblueprint.datamongodb_testcontainers_spring_boot_testing_example.repository.DeviceRepository;
import static org.assertj.core.api.Assertions.assertThat;
@Testcontainers
@DataMongoTest
public class DeviceRepositoryTestContainersTest {
// Start a MongoDB container with the latest image
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:latest");
// Dynamically set the Spring property for MongoDB URI
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
// This provides the connection string to Spring Boot
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
}
@Autowired
private DeviceRepository deviceRepository;
@BeforeEach
void setUp() {
// Clean up database and insert test data
deviceRepository.deleteAll();
Device device = new Device("20", "TCDevice", "Controller", "TCManufacturer");
deviceRepository.save(device);
}
@Test
void findByName_ReturnsDevice() {
// Test retrieval of device by name from MongoDB container
Device device = deviceRepository.findByName("TCDevice").orElse(null);
assertThat(device).isNotNull();
assertThat(device.getType()).isEqualTo("Controller");
assertThat(device.getManufacturer()).isEqualTo("TCManufacturer");
}
}
Key Annotations Explained:
- @Testcontainers – Enables Testcontainers integration.
- @Container – Defines a MongoDB container that runs for the duration of the test class.
- @DynamicPropertySource – Registers the container’s MongoDB URI dynamically.
- @DataMongoTest – Loads only MongoDB-related components for testing.
- @BeforeEach – Cleans up the database and inserts test data before each test.
- @Test – Runs the test case for MongoDB repository methods.
Understanding Transactions in @DataMongoTest
Unlike relational databases, MongoDB does not support transactions in the same way as SQL databases. Therefore, @DataMongoTest does not roll back changes automatically.
If needed, you should manually clean up the database before each test:
deviceRepository.deleteAll();
@BeforeEach
void setUp() {
deviceRepository.deleteAll();
}
@BeforeEach
void setUp() {
deviceRepository.deleteAll();
}
Conclusion
In this guide, we explored how to use @DataMongoTest with Testcontainers to test MongoDB repositories with a real database instance.
Key Takeaways:
Testcontainers provides a real MongoDB instance without requiring local installation.
Automatically starts and stops a MongoDB database for testing.
Dynamically injects database connection properties into Spring Boot.
By following this approach, you can test MongoDB repositories with a real database while keeping your tests fast, isolated, and disposable.