DEV Community

Roger Viñas Alcon
Roger Viñas Alcon

Posted on • Edited on

4 3

Testing a dockerized Spring Boot Application

In this sample we will create a 🍀 Spring Boot Application with a simple /hello endpoint and then distribute it as a 🐳 Docker image

And of course we want to ensure the Docker image works, so we will test it using Testcontainers 🤩

Diagram

Spoiler alert! 👇

GitHub logo rogervinas / spring-boot-docker

🐳 Spring Boot with Docker

Ready? Let's go!

1) We start at Spring Initialzr and create an empty Spring Boot project with Webflux and Kotlin

2) Then we add this simple test

@SpringBootTest(webEnvironment = RANDOM_PORT)
class ApplicationTests {

  @LocalServerPort
  private var port: Int = 0

  @Test
  fun `should say hello`() {
    val responseBody = WebClient.builder()
      .baseUrl("http://localhost:$port").build()
      .get().uri("/hello")
      .exchangeToMono { response ->
        assertThat(response.statusCode()).isEqualTo(HttpStatus.OK)
        response.bodyToMono(String::class.java)
      }.block()
    assertThat(responseBody).isEqualTo("hello!")
  }
}
Enter fullscreen mode Exit fullscreen mode

3) And we add this simple implementation ...

@RestController
class HelloController {

    @GetMapping("/hello")
    fun hello() = "hello!"
}
Enter fullscreen mode Exit fullscreen mode

... and now our test is 🟩👏

4) Next we need to generate a docker image ... 🤔

Some alternatives are documented in Spring Boot with Docker and Topical Guide on Docker

And luckily for us, it is as easy as use the task bootBuildImage of the Spring Boot's Gradle plugin:

./gradlew bootBuildImage
Enter fullscreen mode Exit fullscreen mode

So far so good! 😁

Now we have to test the generated docker image ...

5) First we use org.unbroken-dome.test-sets to create a new test source root named container-test:

plugins {
  id("org.unbroken-dome.test-sets") version "4.0.0"
}

testSets {
    "container-test"()
}

tasks.get("container-test").dependsOn("bootBuildImage")

Enter fullscreen mode Exit fullscreen mode

Note that bootBuildImage task is executed before container-test task, so we ensure we are always testing the docker image we've just built from the current source code

6) Then we create test using Testcontainers and JUnit5

@Testcontainers
class ApplicationContainerTests {

  companion object {

    private const val appPort = 8080

    @Container
    private val app = KGenericContainer(System.getProperty("docker.image"))
      .withExposedPorts(appPort)
  }

  @Test
  fun `should say hello`() {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

7) Last thing we need to do is set the value of the system property docker.image before running any test:

tasks.withType<Test> {
    useJUnitPlatform()
    systemProperty("docker.image", "${project.name}:${project.version}")
}
Enter fullscreen mode Exit fullscreen mode

As ${project.name}:${project.version} is the default value used by bootBuildImage task

And that is all! Happy coding! 💙

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️