SlideShare a Scribd company logo
JUnit5 & TestContainers
Catalog tribe demo

debop@coupang.com
Agenda
• JUnit 5

• TestContainers
JUnit 5
JUnit 5
• JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

• Current version = 5.3.2

• No public modifier needed

• Require Java 8 or higher

• Support in IntelliJ IDEA and Eclipse IDE
Setup
testImplementation “org.junit.jupiter:junit-jupiter-api:$jupiter_version”
testRuntimeOnly “org.junit.jupiter:junit-jupiter-engine:$jupiter_version”
Example import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@BeforeEach
fun setup() {
facts.clear()
}
@Test
fun `facts must have unique name`() {
facts.put("foo", 1)
facts.put("foo", 2)
facts.size shouldEqual 1
assertEquals(2, facts["foo"] !!)
}
Annotations
JUnit 4 JUnit 5
@BeforeClass /
@AfterClass
@BeforeAll / @AfterAll
@Before / @After @BeforeEach/@AfterEach
@Test @Test
@Test(expected=…) Assertions.assertThrows(…) { … }
@Ignore @Disabled
@Nested
@DisplayName
@DisplayName("FactMap operation test")
class FactMapTest {
@Nested
@DisplayName("When same key")
inner class MutableFactMap {
@Test
@DisplayName("When insert duplicated key, update old value")
fun `put same item`() {
val o1 = facts.put("foo", 1)
val o2 = facts.put("foo", 2)
assertNull(o1)
assertEquals(1, o2)
}
}
@Test
fun `facts must have unique name`() {
// …
}
}
@Nested
Assertions
• org.junit.jupiter.api.Assertions

• Use of lambdas for lazy evaluation of messages

• Grouping of assertions

• New way to handle exceptions
Assertions
@Test
fun `put same item`() {
val o1 = facts.put("foo", 1)
val o2 = facts.put("foo", 2)
assertNull(o1) { "o1 should be null" }
assertEquals(1, o2) { "o2 should be 1" }
}
Assertions
assertAll(
Executable { assertNull(o1) { "o1 should be null" } },
Executable { assertEquals(1, o2) { "o2 should be 1" } }
)
assertThrows(IllegalArgumentException::class.java) {
facts.put("", 1)
}
assertTimeout(Duration.ofMillis(200)) {
Thread.sleep(150)
}
assertTimeoutPreemptively(Duration.ofMillis(200)) {
Thread.sleep(150)
}
Assumptions
If assumption fails -> test is skipped
@Test
fun `already exists`() {
// facts is empty -> assumeFalse is failed -> skip assertEquals
assumeFalse { facts.isEmpty() }
// Skip tests
assertEquals(2, 1)
}
Dynamic Tests
@TestFactory
fun testRules(): Stream<DynamicTest> {
return IntStream.range(1, 3)
.mapToObj { it ->
dynamicTest("test for input=$it") {
assertEquals(it * 2, it + it)
}
}
}
https://www.baeldung.com/junit5-dynamic-tests
Conditional Test Execution
• ExecutionCondition as Extension API

• DisabledCondition is simplest example with
@Disabled annotation
Conditional Test Execution
• @EnabledOnOS(…)

• @EnabledOnJre(…)

• @EnabledIfSystemProperty(named=“”, matches=“”)

• @EnabledIfEnvironmentalVariable(named=“”,
matches=“”)

• @EnabledIf(“”) - Support for script, EXPERIMENTAL
Parameterized Tests
• Experimental feature

• Need “junit-jupiter-params”

• Resources

• JUnit 5 Parameterized Tests: Using Different Input 

• JUnit 5 ­ Parameterized Tests
Parameterized Tests
@ParameterizedTest
@ValueSource(strings = ["java8", "java9", "java10"])
fun `parameterized test`(param:String) {
param shouldContain "java"
}
Parameterized Tests
@ParameterizedTest(name = "[{index}]=> {arguments}")
@ValueSource(strings = ["java8", "java9", "java10"])
fun `parameterized test`(param: String) {
param shouldContain "java"
}
Parameterized Tests
• @ValueSource for String, Int, Long, Double)

• @EnumSource(…)

• @MethodSource(“methodName”)

method must return Stream, Iterator or Iterable

• @CsvSource({“foo, bar”, “foo2, bar2”})

• @CsvFileSource(resources=…)

• @ArgumentSource(MyArgProvider.class)
Parallel Test Execution
• Resources

• JUnit 5 Parallel Execution

• JUnit 5 Parallel Test Execution
Parallel Test Execution
junit.jupiter.testinstance.lifecycle.default = per_class
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
#junit.jupiter.execution.parallel.config.strategy = dynamic
#junit.jupiter.execution.parallel.config.dynamic.factor = 1
#junit.jupiter.execution.parallel.config.strategy = fixed
#junit.jupiter.execution.parallel.config.fixed.parallelism = 4
#junit.jupiter.execution.parallel.config.strategy = custom
#junit.jupiter.execution.parallel.config.custom.class = ...
Parallel Test Execution
• Synchronization for shared resources

• @Execution(CONCURRENT)

• @Execution(SAME_THREAD)

• ResourceLock(value=…, mode=…)

• Value

custom|SYSTEM_PROPERTIES|SYSTEM_OUT|SYSTEM_ERR

• Mode

READ | READ_WRITE

• JUnit 5 Synchronization
What else?
• @Tag and filtering in build script

• @RepeatedTest with dynamic placeholder for
@DisplayName

• @TestTemplate/
TestTemplateInvocationContextProvider

• Extension API, extensions registered via @ExtendWith
• Custom Extensions in kotlinx-junit-jupiter
TestContainers
Introduction
• Java library to launch Docker containers during Tests

• Integration tests against the data access layer

• Integration tests with external dependencies

e.g. message broker, database, cache …

• UI Tests with containerized, Selenium compatible,
Web browsers
Introduction
• Current version : 1.10.3

• Requires Docker installation

• Requires Java 8 or higher

• Compatible with JUnit 4 / 5
Usecases
• Data access layer integration tests: use a containerized instance of a
MySQL, PostgreSQL or Oracle database to test your data access layer code for
complete compatibility, but without requiring complex setup on developers'
machines and safe in the knowledge that your tests will always start with a
known DB state.Any other database type that can be containerized can also be
used.
• Application integration tests: for running your application in a short-lived
test mode with dependencies, such as databases, message queues or web servers.
• UI/Acceptance tests: use containerized web browsers, compatible with
Selenium, for conducting automated UI tests. Each test can get a fresh instance of
the browser, with no browser state, plugin variations or automated browser
upgrades to worry about.And you get a video recording of each test session, or
just each session where tests failed.
JUnit 4
@ClassRule
public static GenericContainer mysql =
new MySQLContainer().withExposedPorts(3306);
@Test
public void getExposedPorts() {
List<Integer> ports = mysql.getExposedPorts();
assertThat(ports).contains(3306);
}
JUnit 4 + Kotlin
static {
INSTANCE = createPostgreSQLContainer();
HOST = INSTANCE.getContainerIpAddress();
PORT = INSTANCE.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT);
JDBC_URL = INSTANCE.getJdbcUrl();
}
public static PostgreSQLContainer createPostgreSQLContainer() {
PostgreSQLContainer container = new PostgreSQLContainer();
container.withLogConsumer(new Slf4jLogConsumer(log));
container.withDatabaseName("test");
container.start();
return container;
}
JUnit 5 static GenericContainer mysql =
new MySQLContainer().withExposedPorts(3306);
@BeforeAll
static void setup() {
mysql.start();
}
@AfterAll
static void tearDown() {
mysql.stop();
}
@Test
void getExposedPorts() {
List<Integer> ports = mysql.getExposedPorts();
assertThat(ports).contains(3306);
}
Generic Container
• Offers flexible support for any container image as test
dependency

• Reference public docker images

• Internal dockerized services
Generic Container
• withExposedPorts(…)

• withEnv(…)

• withLabel(…)

• getContainerIpAddress()

• getMappedPort(…)
Generic Container - Kotlin
object RedisContainer : KLogging() {
// For Kotlin language spec
class KGenericContainer(imageName: String) : GenericContainer<KGenericContainer>(imageName)
val instance by lazy { startRedisContainer() }
private fun startRedisContainer() = KGenericContainer("redis:4.0.11").apply {
withExposedPorts(6379)
setWaitStrategy(HostPortWaitStrategy())
withLogConsumer(Slf4jLogConsumer(log))
start()
}
val host: String by lazy { instance.containerIpAddress }
val port: Int by lazy { instance.getMappedPort(6379) }
val url: String by lazy { "redis://$host:$port" }
}
Specialized Container
• Create images from Dockerfile

• withFileFromString(…)

• withFileFromClasspath(…)

• Use Dockerfile DSL to define Dockerfiles in code
Specialized Container
• Use database container to test database specific
features

• No local setup or VM

• 100% database compatibility instead of H2

• MySQL

• PostgreSQL

• Oracle XE
Future
• TestContainers 2.x

• API cleanup

• Decoupling from JUnit 4 to support other
framework directly
Alternatives
• TestNG

• Other JVM languages

• Groovy, Spock, Testcontainers-Spock

• Kotlin, Testcontainers (with workaround)
Resources
• JUnit 5

• JUnit 5 Basic

• JUnit 5 : Next step in automated testing

• How to perform a productivee testing using JUnit 5 on Kotlin 

• Test Containers

• Test containers Official site

• Docker Test Containers in Java Test

• TestContainers and Spring Boot

• Don’t use In-Memory Database (H2, Congo) for Tests
Q&A
Thank you!

More Related Content

PDF
Spring boot introduction
PDF
Testing with JUnit 5 and Spring - Spring I/O 2022
PDF
Terraform modules and best-practices - September 2018
PPTX
TypeScript Overview
PPTX
Asynchronous programming in C#
PDF
Extending kubernetes with CustomResourceDefinitions
PDF
Terraform
PDF
Life as a SRE at Instana
Spring boot introduction
Testing with JUnit 5 and Spring - Spring I/O 2022
Terraform modules and best-practices - September 2018
TypeScript Overview
Asynchronous programming in C#
Extending kubernetes with CustomResourceDefinitions
Terraform
Life as a SRE at Instana

What's hot (20)

PDF
From Postgres to Event-Driven: using docker-compose to build CDC pipelines in...
PPTX
Add an interactive command line to your C++ application
PPTX
Virtualization Vs. Containers
PPTX
Terraform
PDF
Apache Airflow in the Cloud: Programmatically orchestrating workloads with Py...
PPTX
Module 5: YANG Tutorial - part 1
PDF
What's new in Spring Batch 5
PDF
Terraform 101
PPS
the Paxos Commit algorithm
PPT
Jenkins Overview
PPTX
Solid principles
PDF
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
PPTX
PRESENTATION_CHAABA_AYOUB_ING5_ISI.pptx
PPTX
Tail f - Why ConfD
PDF
Terraform introduction
PDF
Apache Spark At Scale in the Cloud
PDF
Testing Spring Boot Applications
PPTX
Docker Kubernetes Istio
PDF
Infinispan for Dummies
PPTX
Introduction to spring boot
From Postgres to Event-Driven: using docker-compose to build CDC pipelines in...
Add an interactive command line to your C++ application
Virtualization Vs. Containers
Terraform
Apache Airflow in the Cloud: Programmatically orchestrating workloads with Py...
Module 5: YANG Tutorial - part 1
What's new in Spring Batch 5
Terraform 101
the Paxos Commit algorithm
Jenkins Overview
Solid principles
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
PRESENTATION_CHAABA_AYOUB_ING5_ISI.pptx
Tail f - Why ConfD
Terraform introduction
Apache Spark At Scale in the Cloud
Testing Spring Boot Applications
Docker Kubernetes Istio
Infinispan for Dummies
Introduction to spring boot
Ad

Similar to JUnit5 and TestContainers (20)

PDF
Integration tests: use the containers, Luke!
PPTX
Easy Java Integration Testing with Testcontainers​
PDF
Testcontainers - Geekout EE 2017 presentation
PDF
Level Up Your Integration Testing With Testcontainers
PDF
GeeCON 2017 - TestContainers. Integration testing without the hassle
PDF
JavaOne 2017 - TestContainers: integration testing without the hassle
PDF
GeeCON Prague 2017 - TestContainers
PDF
Take Control of your Integration Testing with TestContainers
PDF
Prod-Like Integration Testing for Distributed Containerized Applications
PDF
Junit5: the next gen of testing, don't stay behind
PDF
Pragmatic Java Test Automation
PDF
The Groovy Way of Testing with Spock
PDF
Testing with JUnit 5 and Spring
PDF
Make Your Testing Groovy
PPTX
Testcontainers: Reliable, Isolated, and Reproducible Testing for External Dep...
PDF
JavaDay Kiev 2017 - Integration testing with TestContainers
PPTX
Testing Spring Boot application in post-JUnit 4 world
PDF
Testing the frontend
PPTX
Integration testing for microservices with Spring Boot
PPTX
Testing basics for developers
Integration tests: use the containers, Luke!
Easy Java Integration Testing with Testcontainers​
Testcontainers - Geekout EE 2017 presentation
Level Up Your Integration Testing With Testcontainers
GeeCON 2017 - TestContainers. Integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassle
GeeCON Prague 2017 - TestContainers
Take Control of your Integration Testing with TestContainers
Prod-Like Integration Testing for Distributed Containerized Applications
Junit5: the next gen of testing, don't stay behind
Pragmatic Java Test Automation
The Groovy Way of Testing with Spock
Testing with JUnit 5 and Spring
Make Your Testing Groovy
Testcontainers: Reliable, Isolated, and Reproducible Testing for External Dep...
JavaDay Kiev 2017 - Integration testing with TestContainers
Testing Spring Boot application in post-JUnit 4 world
Testing the frontend
Integration testing for microservices with Spring Boot
Testing basics for developers
Ad

More from Sunghyouk Bae (16)

PDF
Introduction of failsafe
PDF
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
PDF
Spring data requery
PDF
Requery overview
PDF
Kotlin @ Coupang Backend 2017
PDF
measure metrics
PDF
Alternatives of JPA/Hibernate
PPTX
Kotlin coroutines and spring framework
PPTX
Java naming strategy (자바 명명 전략)
PPTX
테스트자동화와 TDD
PPTX
SpringBoot with MyBatis, Flyway, QueryDSL
PPTX
JUnit & AssertJ
PPTX
좋은 개발자 되기
PDF
Using AdoRepository
PDF
Multithread pattern 소개
PDF
Strategy Maps
Introduction of failsafe
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Spring data requery
Requery overview
Kotlin @ Coupang Backend 2017
measure metrics
Alternatives of JPA/Hibernate
Kotlin coroutines and spring framework
Java naming strategy (자바 명명 전략)
테스트자동화와 TDD
SpringBoot with MyBatis, Flyway, QueryDSL
JUnit & AssertJ
좋은 개발자 되기
Using AdoRepository
Multithread pattern 소개
Strategy Maps

Recently uploaded (20)

PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Digital Strategies for Manufacturing Companies
PPTX
Introduction to Artificial Intelligence
PPTX
Transform Your Business with a Software ERP System
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Designing Intelligence for the Shop Floor.pdf
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
ai tools demonstartion for schools and inter college
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPT
Introduction Database Management System for Course Database
PPTX
CHAPTER 2 - PM Management and IT Context
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
How to Migrate SBCGlobal Email to Yahoo Easily
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Navsoft: AI-Powered Business Solutions & Custom Software Development
Digital Strategies for Manufacturing Companies
Introduction to Artificial Intelligence
Transform Your Business with a Software ERP System
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Designing Intelligence for the Shop Floor.pdf
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Computer Software and OS of computer science of grade 11.pptx
ai tools demonstartion for schools and inter college
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Softaken Excel to vCard Converter Software.pdf
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Introduction Database Management System for Course Database
CHAPTER 2 - PM Management and IT Context

JUnit5 and TestContainers

  • 2. Agenda • JUnit 5 • TestContainers
  • 4. JUnit 5 • JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage • Current version = 5.3.2 • No public modifier needed • Require Java 8 or higher • Support in IntelliJ IDEA and Eclipse IDE
  • 6. Example import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @BeforeEach fun setup() { facts.clear() } @Test fun `facts must have unique name`() { facts.put("foo", 1) facts.put("foo", 2) facts.size shouldEqual 1 assertEquals(2, facts["foo"] !!) }
  • 7. Annotations JUnit 4 JUnit 5 @BeforeClass / @AfterClass @BeforeAll / @AfterAll @Before / @After @BeforeEach/@AfterEach @Test @Test @Test(expected=…) Assertions.assertThrows(…) { … } @Ignore @Disabled @Nested @DisplayName
  • 8. @DisplayName("FactMap operation test") class FactMapTest { @Nested @DisplayName("When same key") inner class MutableFactMap { @Test @DisplayName("When insert duplicated key, update old value") fun `put same item`() { val o1 = facts.put("foo", 1) val o2 = facts.put("foo", 2) assertNull(o1) assertEquals(1, o2) } } @Test fun `facts must have unique name`() { // … } }
  • 10. Assertions • org.junit.jupiter.api.Assertions • Use of lambdas for lazy evaluation of messages • Grouping of assertions • New way to handle exceptions
  • 11. Assertions @Test fun `put same item`() { val o1 = facts.put("foo", 1) val o2 = facts.put("foo", 2) assertNull(o1) { "o1 should be null" } assertEquals(1, o2) { "o2 should be 1" } }
  • 12. Assertions assertAll( Executable { assertNull(o1) { "o1 should be null" } }, Executable { assertEquals(1, o2) { "o2 should be 1" } } ) assertThrows(IllegalArgumentException::class.java) { facts.put("", 1) } assertTimeout(Duration.ofMillis(200)) { Thread.sleep(150) } assertTimeoutPreemptively(Duration.ofMillis(200)) { Thread.sleep(150) }
  • 13. Assumptions If assumption fails -> test is skipped @Test fun `already exists`() { // facts is empty -> assumeFalse is failed -> skip assertEquals assumeFalse { facts.isEmpty() } // Skip tests assertEquals(2, 1) }
  • 14. Dynamic Tests @TestFactory fun testRules(): Stream<DynamicTest> { return IntStream.range(1, 3) .mapToObj { it -> dynamicTest("test for input=$it") { assertEquals(it * 2, it + it) } } } https://www.baeldung.com/junit5-dynamic-tests
  • 15. Conditional Test Execution • ExecutionCondition as Extension API • DisabledCondition is simplest example with @Disabled annotation
  • 16. Conditional Test Execution • @EnabledOnOS(…) • @EnabledOnJre(…) • @EnabledIfSystemProperty(named=“”, matches=“”) • @EnabledIfEnvironmentalVariable(named=“”, matches=“”) • @EnabledIf(“”) - Support for script, EXPERIMENTAL
  • 17. Parameterized Tests • Experimental feature • Need “junit-jupiter-params” • Resources • JUnit 5 Parameterized Tests: Using Different Input • JUnit 5 ­ Parameterized Tests
  • 18. Parameterized Tests @ParameterizedTest @ValueSource(strings = ["java8", "java9", "java10"]) fun `parameterized test`(param:String) { param shouldContain "java" }
  • 19. Parameterized Tests @ParameterizedTest(name = "[{index}]=> {arguments}") @ValueSource(strings = ["java8", "java9", "java10"]) fun `parameterized test`(param: String) { param shouldContain "java" }
  • 20. Parameterized Tests • @ValueSource for String, Int, Long, Double) • @EnumSource(…) • @MethodSource(“methodName”)
 method must return Stream, Iterator or Iterable • @CsvSource({“foo, bar”, “foo2, bar2”}) • @CsvFileSource(resources=…) • @ArgumentSource(MyArgProvider.class)
  • 21. Parallel Test Execution • Resources • JUnit 5 Parallel Execution • JUnit 5 Parallel Test Execution
  • 22. Parallel Test Execution junit.jupiter.testinstance.lifecycle.default = per_class junit.jupiter.execution.parallel.enabled = true junit.jupiter.execution.parallel.mode.default = concurrent #junit.jupiter.execution.parallel.config.strategy = dynamic #junit.jupiter.execution.parallel.config.dynamic.factor = 1 #junit.jupiter.execution.parallel.config.strategy = fixed #junit.jupiter.execution.parallel.config.fixed.parallelism = 4 #junit.jupiter.execution.parallel.config.strategy = custom #junit.jupiter.execution.parallel.config.custom.class = ...
  • 23. Parallel Test Execution • Synchronization for shared resources • @Execution(CONCURRENT) • @Execution(SAME_THREAD) • ResourceLock(value=…, mode=…) • Value
 custom|SYSTEM_PROPERTIES|SYSTEM_OUT|SYSTEM_ERR • Mode
 READ | READ_WRITE • JUnit 5 Synchronization
  • 24. What else? • @Tag and filtering in build script • @RepeatedTest with dynamic placeholder for @DisplayName • @TestTemplate/ TestTemplateInvocationContextProvider • Extension API, extensions registered via @ExtendWith • Custom Extensions in kotlinx-junit-jupiter
  • 26. Introduction • Java library to launch Docker containers during Tests • Integration tests against the data access layer • Integration tests with external dependencies
 e.g. message broker, database, cache … • UI Tests with containerized, Selenium compatible, Web browsers
  • 27. Introduction • Current version : 1.10.3 • Requires Docker installation • Requires Java 8 or higher • Compatible with JUnit 4 / 5
  • 28. Usecases • Data access layer integration tests: use a containerized instance of a MySQL, PostgreSQL or Oracle database to test your data access layer code for complete compatibility, but without requiring complex setup on developers' machines and safe in the knowledge that your tests will always start with a known DB state.Any other database type that can be containerized can also be used. • Application integration tests: for running your application in a short-lived test mode with dependencies, such as databases, message queues or web servers. • UI/Acceptance tests: use containerized web browsers, compatible with Selenium, for conducting automated UI tests. Each test can get a fresh instance of the browser, with no browser state, plugin variations or automated browser upgrades to worry about.And you get a video recording of each test session, or just each session where tests failed.
  • 29. JUnit 4 @ClassRule public static GenericContainer mysql = new MySQLContainer().withExposedPorts(3306); @Test public void getExposedPorts() { List<Integer> ports = mysql.getExposedPorts(); assertThat(ports).contains(3306); }
  • 30. JUnit 4 + Kotlin static { INSTANCE = createPostgreSQLContainer(); HOST = INSTANCE.getContainerIpAddress(); PORT = INSTANCE.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT); JDBC_URL = INSTANCE.getJdbcUrl(); } public static PostgreSQLContainer createPostgreSQLContainer() { PostgreSQLContainer container = new PostgreSQLContainer(); container.withLogConsumer(new Slf4jLogConsumer(log)); container.withDatabaseName("test"); container.start(); return container; }
  • 31. JUnit 5 static GenericContainer mysql = new MySQLContainer().withExposedPorts(3306); @BeforeAll static void setup() { mysql.start(); } @AfterAll static void tearDown() { mysql.stop(); } @Test void getExposedPorts() { List<Integer> ports = mysql.getExposedPorts(); assertThat(ports).contains(3306); }
  • 32. Generic Container • Offers flexible support for any container image as test dependency • Reference public docker images • Internal dockerized services
  • 33. Generic Container • withExposedPorts(…) • withEnv(…) • withLabel(…) • getContainerIpAddress() • getMappedPort(…)
  • 34. Generic Container - Kotlin object RedisContainer : KLogging() { // For Kotlin language spec class KGenericContainer(imageName: String) : GenericContainer<KGenericContainer>(imageName) val instance by lazy { startRedisContainer() } private fun startRedisContainer() = KGenericContainer("redis:4.0.11").apply { withExposedPorts(6379) setWaitStrategy(HostPortWaitStrategy()) withLogConsumer(Slf4jLogConsumer(log)) start() } val host: String by lazy { instance.containerIpAddress } val port: Int by lazy { instance.getMappedPort(6379) } val url: String by lazy { "redis://$host:$port" } }
  • 35. Specialized Container • Create images from Dockerfile • withFileFromString(…) • withFileFromClasspath(…) • Use Dockerfile DSL to define Dockerfiles in code
  • 36. Specialized Container • Use database container to test database specific features • No local setup or VM • 100% database compatibility instead of H2 • MySQL • PostgreSQL • Oracle XE
  • 37. Future • TestContainers 2.x • API cleanup • Decoupling from JUnit 4 to support other framework directly
  • 38. Alternatives • TestNG • Other JVM languages • Groovy, Spock, Testcontainers-Spock • Kotlin, Testcontainers (with workaround)
  • 39. Resources • JUnit 5 • JUnit 5 Basic • JUnit 5 : Next step in automated testing • How to perform a productivee testing using JUnit 5 on Kotlin • Test Containers • Test containers Official site • Docker Test Containers in Java Test • TestContainers and Spring Boot • Don’t use In-Memory Database (H2, Congo) for Tests
  • 40. Q&A