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 ๐คฉ
Ready? Let's go!
You can browse older versions:
@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!")
}
}
@RestController
class HelloController {
@GetMapping("/hello")
fun hello() = "hello!"
}
... and now our test is ๐ฉ๐
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
So far so good! ๐
Now we have to test the generated docker image ...
container-test
:plugins {
id("org.unbroken-dome.test-sets") version "x.x.x"
}
testSets {
"container-test"()
}
tasks["container-test"].dependsOn("bootBuildImage")
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
@Testcontainers
class ApplicationContainerTests {
companion object {
private const val APP_PORT = 8080
@Container
private val app = GenericContainer(System.getProperty("docker.image"))
.withExposedPorts(APP_PORT)
}
@Test
fun `should say hello`() {
// ...
}
}
docker.image
before running any test:tasks.withType<Test> {
useJUnitPlatform()
systemProperty("docker.image", "${project.name}:${project.version}")
}
As ${project.name}:${project.version}
is the default value used by bootBuildImage
task
And that is all! Happy coding! ๐
Test the application without assembling it:
./gradlew test
Build the application as a container and test it:
./gradlew container-test
Run the application without assembling it:
./gradlew bootRun
Build the application as a fatjar and run it with java:
./gradlew bootJar
java -jar ./build/libs/spring-boot-docker-0.0.1-SNAPSHOT.jar
Build the application as a container and run it with docker:
./gradlew bootBuildImage
docker run -p 8080:8080 --rm spring-boot-docker:0.0.1-SNAPSHOT
In either case, call the /hello endpoint:
curl -i http://localhost:8080/hello