DEV Community

K. Siva Prasad Reddy
K. Siva Prasad Reddy

Posted on

12 1

SpringBoot Integration Testing using TestContainers Starter

One of the many reasons for huge popularity of Spring and SpringBoot is
it's great support for Testing.
We can write unit tests using Mockito without requiring any Spring features. And, we can write Integration Tests using Spring testing support by creating Spring ApplicationContext.

Read Guide to Testing SpringBoot Applications

While running integration tests we might need to interact with external services like relational databases, NoSQL datastores, Kafka etc. We can spin up those external services as Docker containers and run tests against them.

Testcontainers

From Testcontainers docs:

Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

We can use Testcontainers to spin up a Singleton docker container
in a SpringBoot integration test as follows:

@SpringBootTest
@ContextConfiguration(initializers = {UserServiceIntegrationTest.Initializer.class})
class UserServiceIntegrationTest {
    private static PostgreSQLContainer sqlContainer;

    static {
        sqlContainer = new PostgreSQLContainer("postgres:10.7")
                .withDatabaseName("integration-tests-db")
                .withUsername("sa")
                .withPassword("sa");
        sqlContainer.start();
    }

    static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            TestPropertyValues.of(
              "spring.datasource.url=" + sqlContainer.getJdbcUrl(),
              "spring.datasource.username=" + sqlContainer.getUsername(),
              "spring.datasource.password=" + sqlContainer.getPassword()
            ).applyTo(configurableApplicationContext.getEnvironment());
        }
    }

    @Autowired
    private UserService userService;

    @Test
    void shouldGetAllUsers() {
        // test userService.getAllUsers()
    }   

}

This is such a very common requirement in SpringBoot applications, so the community built Testcontainers SpringBoot starter to make it more easy.

Testcontainers SpringBoot starter

The Testcontainers SpringBoot starter depends on spring-cloud-starter. If you are NOT already using any SpringCloud starters in the application then include spring-cloud-starter as a test dependency.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter</artifactId>
    <scope>test</scope>
</dependency>

Now include data service library depending on what data service you need.
For example if you want to use Postgresql docker container then add the following dependency:

<dependency>
    <groupId>com.playtika.testcontainers</groupId>
    <artifactId>embedded-postgresql</artifactId>
    <scope>test</scope>
</dependency>

When you add the embedded-postgresql dependency then following properties will be added to the Environment:

  • embedded.postgresql.port
  • embedded.postgresql.host
  • embedded.postgresql.schema
  • embedded.postgresql.user
  • embedded.postgresql.password

We can use these properties to configure datasource properties for testing.

Usually we want to spin up docker containers for integration tests but not for unit tests. So we can disable it by default and only enable during integration tests by using profile based configuration.

src/test/resources/bootstrap.properties

embedded.postgresql.enabled=false

src/test/resources/bootstrap-integration-test.properties

embedded.postgresql.enabled=true
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://${embedded.postgresql.host}:${embedded.postgresql.port}/${embedded.postgresql.schema}
spring.datasource.username=${embedded.postgresql.user}
spring.datasource.password=${embedded.postgresql.password}

Now we can run integration tests with integration-test profile using @ActiveProfiles as follows:

@SpringBootTest
@ActiveProfiles("integration-test")
class UserServiceIntegrationTest {

    @Autowired
    private UserService userService;

    @Test
    void shouldGetAllUsers() {
        // test userService.getAllUsers()
    }   

}

We may want to use specific version of a docker image, then you can configure it as follows:

src/test/resources/bootstrap-integration-test.properties

embedded.postgresql.dockerImage=postgres:10.7
embedded.postgresql.enabled=true

The Testcontainers SpringBoot starter already provide support for most commonly used containers like Postgresql, MariaDB, MongoDB, Redis, RabbitMQ, Kafka, Elasticsearch etc.

To my surprise there is no direct support for MySQL as of now. But there is a simple workaround for this as described here https://github.com/testcontainers/testcontainers-spring-boot/issues/151.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (4)

Collapse
 
ewoks profile image
Beeblebrox • • Edited

Thanks for the nice article. I recently found great course that among other things shows use of test containers too (bit.ly/2PahMnl 🚀)
Cool tools, I really like TestContainers :) Regarding MySQL, did you check github.com/Playtika/testcontainers...

Looking forward to more of your posts

Collapse
 
danikofficial profile image
DanikOfficial •

Thank you very much, you gave me a simple explanation...

Collapse
 
vasilievip profile image

mysql autoconfig is available now
github.com/testcontainers/testcont...

Collapse
 
pedro_grijalva profile image
Pedro Grijalva •

Hi, where is the code repository of the article? thanks

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

đź‘‹ Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay