Spring Testcontainers (MongoDB)
https://github.com/spring-boot-tutorials/spring-testcontainers-mongodb
In this article we will configure Spring Testcontainers MongoDB.
Create Initial Code Base
Go to https://start.spring.io/
Add the following dependencies:
spring-boot-starter-data-mongodb
spring-boot-starter-web
spring-boot-testcontainers
lombok
Click Generate
Dependencies
Dependencies in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
Model
Create new POJO class src/main/java/com/example/spring_testcontainers/Author.java
:
@Data
@SuperBuilder
@Document(collection = "authors")
@NoArgsConstructor
@AllArgsConstructor
public class Author {
@Id
@Indexed(unique = true)
@Field(name = "_id")
private String id = UUID.randomUUID().toString();
@Field(name = "full_name")
private String name;
@Indexed(unique = true)
private String email;
@Field(name = "num_articles")
private Integer articleCount;
private Boolean active;
public Boolean isActive() {
return this.active;
}
}
Repository
Create new file src/main/java/com/example/spring_testcontainers/AuthorRepository.java
:
public interface AuthorRepository extends MongoRepository<Author, String> {
List<Author> findByEmail(String email);
List<Author> findByActiveTrueAndArticleCountGreaterThanEqual(int articleCount);
@Query("{ 'num_articles': { $gte: ?0, $lte: ?1 }, 'active': true }")
List<Author> findActiveAuthorsInArticleRange(int minArticles, int maxArticles);
// Returns active authors JUST email
@Query(value = "{ 'active': true }", fields = "{ 'email': 1 }")
List<Author> findActiveAuthorEmails();
}
Controller
Let’s create a new file src/main/java/com/example/spring_testcontainers/AuthorController.java
@RestController
@RequestMapping("characters")
@RequiredArgsConstructor
public class AuthorController {
private final AuthorRepository repository;
// curl http://localhost:8080/characters
@GetMapping
public List<Author> findAll() {
return repository.findAll();
}
// curl -X POST -H "Content-Type: application/json" -d '{"id": "id-1", "name": "marcus chiu", "email": "marcuschiu9@gmail.com"}' http://localhost:8080/characters
// curl -X POST -H "Content-Type: application/json" -d '{"id": "id-2", "name": "marcus chiu", "email": "marcuschiu9@gmail.com"}' http://localhost:8080/characters
@PostMapping
public Author save(@RequestBody Author character) {
return repository.save(character);
}
}
Create Tests #1
Create new file src/test/java/com/example/spring_testcontainers/individual/ServiceConnectionIntegrationTest.java
:
@Testcontainers
@SpringBootTest(webEnvironment = DEFINED_PORT)
class ServiceConnectionIntegrationTest {
@Container
@ServiceConnection
static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:7.0"));
@Autowired
AuthorRepository repository;
@Autowired
TestRestTemplate restTemplate;
@Test
void given_when_then() {
// given
repository.saveAll(List.of(
new Author(UUID.randomUUID().toString(), "name-1", "email-1", 1, true),
new Author(UUID.randomUUID().toString(), "name-2", "email-2", 1, true),
new Author(UUID.randomUUID().toString(), "name-3", "email-3", 1, true),
new Author(UUID.randomUUID().toString(), "name-4", "email-4", 1, true)
));
ResponseEntity<String> response = restTemplate.getForEntity("/characters", String.class);
assertThat(response.getStatusCode().is2xxSuccessful()).isTrue();
assertThat(response.getBody()).contains("name-1", "name-2", "name-3", "name-4");
}
}
Run Test #1
mvn clean package
Create Local Development Environment
Create the following files:
src/test/java/com/example/spring_testcontainers/localdevelopment/TestcontainersConfiguration.java
src/test/java/com/example/spring_testcontainers/localdevelopment/SpringTestcontainersApplicationTests.java
src/test/java/com/example/spring_testcontainers/localdevelopment/TestSpringTestcontainersApplication.java
@TestConfiguration(proxyBeanMethods = false)
class TestcontainersConfiguration {
@Bean
@ServiceConnection
public MongoDBContainer mongoDBContainer() {
return new MongoDBContainer(DockerImageName.parse("mongo:7.0"));
}
}
@Import(TestcontainersConfiguration.class)
@SpringBootTest
class SpringTestcontainersApplicationTests {
@Test
void contextLoads() {
}
}
public class TestSpringTestcontainersApplication {
public static void main(String[] args) {
SpringApplication.from(SpringTestcontainersApplication::main)
.with(TestcontainersConfiguration.class)
.run(args);
}
}
Run Local Development Environment
If you have IntelliJ as an IDE you could right click TestSpringTestcontainersApplication
and click run
.