SlideShare a Scribd company logo
1 of 48
Download to read offline
Level Up Your Integration Testing
With Testcontainers
Dan Vega ⸱ @therealdanvega
Developer Advocate, VMware
⸺
Cora Iberkleid ⸱ @ciberkleid
Developer Advocate, VMware
⸺
Maria Gabriella Brodi ⸱ @BrodiMg
Staff Solutions Engineer, VMware
Abstract - SpringOne Tour
Traditional approaches to integration testing—using shared, local, or in-memory databases—fall short for
today's modern developer.
Developers today are building cloud native distributed microservices and taking advantage of a rich variety
of backing services. This explosion of applications and backing services introduces new challenges in
creating the necessary environments for integration testing. To be useful and effective, these environments
must be easy to create and they must resemble production as closely as possible. New solutions are needed
to make this need a reality.
Enter Testcontainers!
Testcontainers is a Java library that supports JUnit tests and makes it incredibly easy to create lightweight,
throwaway instances of common databases, Selenium web browsers, or anything else that can run in a
Docker container.
Testing is important
Testing can be hard
“You have to make the
right thing to do, the easy
thing to do.”
- Cora Iberkleid
Agenda
● Intro
● Testcontainers 101
● Spring Boot Demo
● Q&A
INTRO
“Prod-like” integration testing - what do we mean?
● Integration vs Unit tests
● Greater fidelity to run-time conditions
○ Type of system
○ Network reliability
○ OS environment
● Shifted left
○ Local developer machine
○ Iterate locally
Common approaches to integration testing
In Integration tests we are interested in verifying the behavior and interactions of
multiple modules.
For this purpose we can use:
● Shared instances
● Local installation
● In memory solutions
In-memory testing
App
Mock server or
in-memory service
Options:
● Mock server (Wiremock, Loki…)
● In-memory service (h2, hsql...)
Limitations of in-memory testing
App
Mock server or
in-memory service
Limitations:
● Requires framework support
● Behavior differences to real system
● Latency/bandwidth testing can be
challenging
● Not every service has an in-memory
option
● Differences in security configuration
New challenges with in-memory testing
App
Challenge exacerbated with explosion in microservices
and variety of service options over the last 10 years.
Mock server or
in-memory service
Limitations:
● Requires framework support
● Behavior differences to real system
● Latency/bandwidth testing can be
challenging
● Not every service has an in-memory
option
● Differences in security configuration
New challenges with in-memory testing
App
Challenge exacerbated with explosion in microservices
and variety of service options over the last 10 years.
Mock server or
in-memory service
Limitations:
● Requires framework support
● Behavior differences to real system
● Latency/bandwidth testing can be
challenging
● Not every service has an in-memory
option
● Differences in security configuration
Containerization Helps!
● Containerization per se is a big part of the solution
● Docker Compose - works for any framework
However…
● Cumbersome lifecycle management
● Additional skill set for developers to learn
However!
● There is an easier solution :)
Testcontainers: easy testing with external services
Service on Docker
App
Testcontainers
dependency
TESTCONTAINERS 101
Testcontainers intro/overview
● Java library that creates instances of Docker containers for testing
● Supports JUnit4, JUnit5, and Spock
Support for other languages
(check GitHub for more complete information)
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
● Can start anything else
that can run in a Docker
container
● Can run containers on
your local Docker or in
the Testcontainers Cloud
SaaS platform (beta)
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
Available modules
● Provides lightweight,
throwaway instances of
common databases,
Selenium web browsers,
and more
● Can start anything else
that can run in a Docker
container
Whale by Artzgeo on Noun Project
And in the
cloud!
Testcontainers
Cloud
SaaS Platform (beta)
https:/
/testcontainers.cloud
Photo by Engin Akyurt on Unsplash
Whale by Artzgeo on Noun Project
X
Why Testcontainers? Where to use them?
● Prod-like systems:
● Easier instantiation of disposable services that lack an in-memory option
● Test against any application that can run as a container
● Integration testing:
● Data access layer integration
● Application integration
● Browser-based acceptance
inspiration...
package org.testcontainers.junit.jupiter;
import ...
class TestcontainersExtension implements BeforeEachCallback, BeforeAllCallback,
AfterEachCallback, AfterAllCallback, ExecutionCondition, TestInstancePostProcessor {
@Testcontainers (JUnit 5)
JUnit5 Extension - intercepts JUnit lifecycle
events and manages container lifecycles
@Testcontainers
public class MyIntegrationTests {
@Container // In JUnit 4, use @Rule/@ClassRule
static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres");
...
@ExtendWith({TestcontainersExtension.class})
@Container (JUnit 5) / @Rule (JUnit 4)
@Testcontainers
public class MyIntegrationTests {
@Container // In JUnit 4, use @Rule/@ClassRule
PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres");
...
Flags TestcontainersExtension about a container to manage
● New container is started/stopped for every test
● Declare as static to re-use the same container
JUnit Test Lifecycle & Testcontainer Callbacks
BeforeAllCallback
BeforeEachCallback
AfterAllCallback
AfterEachCallback
ExecutionCondition
TestInstancePostProcessor
JUnit Test Lifecycle
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
No testcontainers
default action in
@BeforeAll
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
No testcontainers action
in Constructor
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
@BeforeEach, Test1:
Connect to docker
Start ryuk
Check system
Start container
Execute BeforeEach method
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
No testcontainers action
in @Test
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
After Test 1 “AfterEach”,
Ryuk cleans up container
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
In Constructor. Class instance: LifeCycleTest@42d236fb
Constructor creates a
new class instance
Test 2
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
In Constructor. Class instance: LifeCycleTest@42d236fb
Container myRepo/myImg is starting:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
@BeforeEach, Test2:
Start new container
Execute BeforeEach method
Test 2
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
In Constructor. Class instance: LifeCycleTest@42d236fb
Container myRepo/myImg is starting:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @Test 2. Class instance: LifeCycleTest@42d236fb
No testcontainers action
in @Test
Test 2
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
In Constructor. Class instance: LifeCycleTest@42d236fb
Container myRepo/myImg is starting:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @Test 2. Class instance: LifeCycleTest@42d236fb
In @AfterEach. Class instance: LifeCycleTest@42d236fb
Ryuk removed container and associated volume(s): myRepo/myImg
In @AfterAll. Static method.
After Test 2 “AfterEach”,
Ryuk cleans up container
Test 2
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@17d88132
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Pulling docker image: testcontainers/ryuk
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Pulling docker image: myRepo/myImg
Container myRepo/myImg is starting:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id:
b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5
In @Test 1. Class instance: LifeCycleTest@17d88132
In @AfterEach. Class instance: LifeCycleTest@17d88132
Ryuk removed container and associated volume(s): myRepo/myImg
In Constructor. Class instance: LifeCycleTest@42d236fb
Container myRepo/myImg is starting:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id:
20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1
In @Test 2. Class instance: LifeCycleTest@42d236fb
In @AfterEach. Class instance: LifeCycleTest@42d236fb
Ryuk removed container and associated volume(s): myRepo/myImg
In @AfterAll. Static method.
No testcontainers
default action in
@AfterAll
Test 2
Test 1
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
static GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
@Testcontainers
@Slf4j
public class LifeCycleTest {
@Container
static GenericContainer container = new
GenericContainer(DockerImageName.parse("myRepo/myImg"));
public LifeCycleTest() {
log.info("In Constructor. Class instance: ", this);
}
@BeforeAll
public static void beforeAllMethod() {
log.info("In @BeforeAll. Static method.");
}
@BeforeEach
public void beforeEachMethod() {
log.info("In @BeforeEach. Class instance: " + this
+ ", Container id: ", container.getContainerId());
}
@Test
public void test1() {
log.info("In @Test 1. Class instance: ", this);
}
@Test
public void test2() {
log.info("In @Test 2. Class instance: ", this);
}
@AfterEach
public void afterEachMethod() {
log.info("In @AfterEach. Class instance: ", this);
}
@AfterAll
public static void afterAllMethod() {
log.info("In @AfterAll. Static method.");
}
}
Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
Connected to docker
Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
Checking the system...
✔ Docker server version should be at least 1.6.0
✔ Docker environment should have more than 2GB free disk space
Container myRepo/myImg is starting:
8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a
In @BeforeAll. Static method.
In Constructor. Class instance: LifeCycleTest@63a5d002
In @BeforeEach. Class instance: LifeCycleTest@63a5d002, Container id:
8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a
In @Test 1. Class instance: LifeCycleTest@63a5d002
In @AfterEach. Class instance: LifeCycleTest@63a5d002
In Constructor. Class instance: LifeCycleTest@60e949e1
In @BeforeEach. Class instance: LifeCycleTest@60e949e1, Container id:
8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a
In @Test 2. Class instance: LifeCycleTest@60e949e1
In @AfterEach. Class instance: LifeCycleTest@60e949e1
In @AfterAll. Static method.
Ryuk removed container and associated volume(s): myRepo/myImg
Container is reused
across tests
Test 2
Test 1
Spring Boot ❤ Testcontainers
https://github.com/danvega/reading-list
Q&A

More Related Content

What's hot

Connecting Connect with Spring Boot
Connecting Connect with Spring BootConnecting Connect with Spring Boot
Connecting Connect with Spring BootVincent Kok
 
Introduction to ASP.NET Core
Introduction to ASP.NET CoreIntroduction to ASP.NET Core
Introduction to ASP.NET CoreAvanade Nederland
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot IntroductionJeevesh Pandey
 
Docker and kubernetes_introduction
Docker and kubernetes_introductionDocker and kubernetes_introduction
Docker and kubernetes_introductionJason Hu
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSRafael Casuso Romate
 
Docker swarm introduction
Docker swarm introductionDocker swarm introduction
Docker swarm introductionEvan Lin
 
Maven 3 Overview
Maven 3  OverviewMaven 3  Overview
Maven 3 OverviewMike Ensor
 
TestNG Annotations in Selenium | Edureka
TestNG Annotations in Selenium | EdurekaTestNG Annotations in Selenium | Edureka
TestNG Annotations in Selenium | EdurekaEdureka!
 
UFT Automation Framework Introduction
UFT Automation Framework IntroductionUFT Automation Framework Introduction
UFT Automation Framework IntroductionHimal Bandara
 

What's hot (20)

Connecting Connect with Spring Boot
Connecting Connect with Spring BootConnecting Connect with Spring Boot
Connecting Connect with Spring Boot
 
Introduction to ASP.NET Core
Introduction to ASP.NET CoreIntroduction to ASP.NET Core
Introduction to ASP.NET Core
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
Docker and kubernetes_introduction
Docker and kubernetes_introductionDocker and kubernetes_introduction
Docker and kubernetes_introduction
 
Project Lombok!
Project Lombok!Project Lombok!
Project Lombok!
 
Hybrid framework
Hybrid frameworkHybrid framework
Hybrid framework
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
 
Docker swarm introduction
Docker swarm introductionDocker swarm introduction
Docker swarm introduction
 
Maven Overview
Maven OverviewMaven Overview
Maven Overview
 
Maven 3 Overview
Maven 3  OverviewMaven 3  Overview
Maven 3 Overview
 
Maven tutorial
Maven tutorialMaven tutorial
Maven tutorial
 
Maven Introduction
Maven IntroductionMaven Introduction
Maven Introduction
 
TestNG Annotations in Selenium | Edureka
TestNG Annotations in Selenium | EdurekaTestNG Annotations in Selenium | Edureka
TestNG Annotations in Selenium | Edureka
 
UFT Automation Framework Introduction
UFT Automation Framework IntroductionUFT Automation Framework Introduction
UFT Automation Framework Introduction
 
Introduction to Maven
Introduction to MavenIntroduction to Maven
Introduction to Maven
 
Rest assured
Rest assuredRest assured
Rest assured
 
Automation Testing by Selenium Web Driver
Automation Testing by Selenium Web DriverAutomation Testing by Selenium Web Driver
Automation Testing by Selenium Web Driver
 
Rest API
Rest APIRest API
Rest API
 
MuleSoft JWT Demystified
MuleSoft JWT DemystifiedMuleSoft JWT Demystified
MuleSoft JWT Demystified
 

Similar to Level Up Your Integration Testing With Testcontainers

Prod-Like Integration Testing for Distributed Containerized Applications
Prod-Like Integration Testing for Distributed Containerized ApplicationsProd-Like Integration Testing for Distributed Containerized Applications
Prod-Like Integration Testing for Distributed Containerized ApplicationsVMware Tanzu
 
JLove - Replicating production on your laptop using the magic of containers
JLove - Replicating production on your laptop using the magic of containersJLove - Replicating production on your laptop using the magic of containers
JLove - Replicating production on your laptop using the magic of containersGrace Jansen
 
JBCN_Testing_With_Containers
JBCN_Testing_With_ContainersJBCN_Testing_With_Containers
JBCN_Testing_With_ContainersGrace Jansen
 
Anatomy of a Build Pipeline
Anatomy of a Build PipelineAnatomy of a Build Pipeline
Anatomy of a Build PipelineSamuel Brown
 
Easy Java Integration Testing with Testcontainers​
Easy Java Integration Testing with Testcontainers​Easy Java Integration Testing with Testcontainers​
Easy Java Integration Testing with Testcontainers​Payara
 
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31Masayuki Igawa
 
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...Throwing complexity over the wall: Rapid development for enterprise Java (Jav...
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...Dan Allen
 
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...Sauce Labs
 
Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)CIVEL Benoit
 
Cerberus_Presentation1
Cerberus_Presentation1Cerberus_Presentation1
Cerberus_Presentation1CIVEL Benoit
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?Dmitry Buzdin
 
Into The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsInto The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsOrtus Solutions, Corp
 
Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality
 Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality
Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to realityDaniel Gallego Vico
 
Resilience Testing
Resilience Testing Resilience Testing
Resilience Testing Ran Levy
 
Cloud Native Dünyada CI/CD
Cloud Native Dünyada CI/CDCloud Native Dünyada CI/CD
Cloud Native Dünyada CI/CDMustafa AKIN
 
190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
190711_Testbirds_Selenium_eclipsecon_FINAL_0.pptNaviAningi
 
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.pptKKSD_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.pptKiran Kumar SD
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projectsVincent Massol
 
Creating Realistic Unit Tests with Testcontainers
Creating Realistic Unit Tests with TestcontainersCreating Realistic Unit Tests with Testcontainers
Creating Realistic Unit Tests with TestcontainersPaul Balogh
 

Similar to Level Up Your Integration Testing With Testcontainers (20)

Prod-Like Integration Testing for Distributed Containerized Applications
Prod-Like Integration Testing for Distributed Containerized ApplicationsProd-Like Integration Testing for Distributed Containerized Applications
Prod-Like Integration Testing for Distributed Containerized Applications
 
JLove - Replicating production on your laptop using the magic of containers
JLove - Replicating production on your laptop using the magic of containersJLove - Replicating production on your laptop using the magic of containers
JLove - Replicating production on your laptop using the magic of containers
 
JBCN_Testing_With_Containers
JBCN_Testing_With_ContainersJBCN_Testing_With_Containers
JBCN_Testing_With_Containers
 
Anatomy of a Build Pipeline
Anatomy of a Build PipelineAnatomy of a Build Pipeline
Anatomy of a Build Pipeline
 
Advanced Java Testing
Advanced Java TestingAdvanced Java Testing
Advanced Java Testing
 
Easy Java Integration Testing with Testcontainers​
Easy Java Integration Testing with Testcontainers​Easy Java Integration Testing with Testcontainers​
Easy Java Integration Testing with Testcontainers​
 
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31
Ensuring OpenStack Version up Compatibility for CloudOpen Japan 2013-05-31
 
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...Throwing complexity over the wall: Rapid development for enterprise Java (Jav...
Throwing complexity over the wall: Rapid development for enterprise Java (Jav...
 
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...
Slow, Flaky and Legacy Tests: FTFY - Our New Testing Strategy at Net-A-Porter...
 
Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)
 
Cerberus_Presentation1
Cerberus_Presentation1Cerberus_Presentation1
Cerberus_Presentation1
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?
 
Into The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsInto The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applications
 
Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality
 Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality
Droidcon Spain 2016 - The Pragmatic Android Programmer: from hype to reality
 
Resilience Testing
Resilience Testing Resilience Testing
Resilience Testing
 
Cloud Native Dünyada CI/CD
Cloud Native Dünyada CI/CDCloud Native Dünyada CI/CD
Cloud Native Dünyada CI/CD
 
190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
190711_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
 
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.pptKKSD_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
KKSD_Testbirds_Selenium_eclipsecon_FINAL_0.ppt
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projects
 
Creating Realistic Unit Tests with Testcontainers
Creating Realistic Unit Tests with TestcontainersCreating Realistic Unit Tests with Testcontainers
Creating Realistic Unit Tests with Testcontainers
 

More from VMware Tanzu

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItVMware Tanzu
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023VMware Tanzu
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleVMware Tanzu
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023VMware Tanzu
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductVMware Tanzu
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready AppsVMware Tanzu
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And BeyondVMware Tanzu
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023VMware Tanzu
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptxVMware Tanzu
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchVMware Tanzu
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishVMware Tanzu
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVMware Tanzu
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - FrenchVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023VMware Tanzu
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootVMware Tanzu
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerVMware Tanzu
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeVMware Tanzu
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsVMware Tanzu
 

More from VMware Tanzu (20)

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
 

Recently uploaded

Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 

Recently uploaded (20)

Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 

Level Up Your Integration Testing With Testcontainers

  • 1. Level Up Your Integration Testing With Testcontainers Dan Vega ⸱ @therealdanvega Developer Advocate, VMware ⸺ Cora Iberkleid ⸱ @ciberkleid Developer Advocate, VMware ⸺ Maria Gabriella Brodi ⸱ @BrodiMg Staff Solutions Engineer, VMware
  • 2. Abstract - SpringOne Tour Traditional approaches to integration testing—using shared, local, or in-memory databases—fall short for today's modern developer. Developers today are building cloud native distributed microservices and taking advantage of a rich variety of backing services. This explosion of applications and backing services introduces new challenges in creating the necessary environments for integration testing. To be useful and effective, these environments must be easy to create and they must resemble production as closely as possible. New solutions are needed to make this need a reality. Enter Testcontainers! Testcontainers is a Java library that supports JUnit tests and makes it incredibly easy to create lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
  • 5. “You have to make the right thing to do, the easy thing to do.” - Cora Iberkleid
  • 6. Agenda ● Intro ● Testcontainers 101 ● Spring Boot Demo ● Q&A
  • 8. “Prod-like” integration testing - what do we mean? ● Integration vs Unit tests ● Greater fidelity to run-time conditions ○ Type of system ○ Network reliability ○ OS environment ● Shifted left ○ Local developer machine ○ Iterate locally
  • 9. Common approaches to integration testing In Integration tests we are interested in verifying the behavior and interactions of multiple modules. For this purpose we can use: ● Shared instances ● Local installation ● In memory solutions
  • 10. In-memory testing App Mock server or in-memory service Options: ● Mock server (Wiremock, Loki…) ● In-memory service (h2, hsql...)
  • 11. Limitations of in-memory testing App Mock server or in-memory service Limitations: ● Requires framework support ● Behavior differences to real system ● Latency/bandwidth testing can be challenging ● Not every service has an in-memory option ● Differences in security configuration
  • 12. New challenges with in-memory testing App Challenge exacerbated with explosion in microservices and variety of service options over the last 10 years. Mock server or in-memory service Limitations: ● Requires framework support ● Behavior differences to real system ● Latency/bandwidth testing can be challenging ● Not every service has an in-memory option ● Differences in security configuration
  • 13. New challenges with in-memory testing App Challenge exacerbated with explosion in microservices and variety of service options over the last 10 years. Mock server or in-memory service Limitations: ● Requires framework support ● Behavior differences to real system ● Latency/bandwidth testing can be challenging ● Not every service has an in-memory option ● Differences in security configuration
  • 14. Containerization Helps! ● Containerization per se is a big part of the solution ● Docker Compose - works for any framework However… ● Cumbersome lifecycle management ● Additional skill set for developers to learn However! ● There is an easier solution :)
  • 15. Testcontainers: easy testing with external services Service on Docker App Testcontainers dependency
  • 17. Testcontainers intro/overview ● Java library that creates instances of Docker containers for testing ● Supports JUnit4, JUnit5, and Spock
  • 18. Support for other languages (check GitHub for more complete information)
  • 19. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more ● Can start anything else that can run in a Docker container ● Can run containers on your local Docker or in the Testcontainers Cloud SaaS platform (beta)
  • 20. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 21. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 22. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 23. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 24. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 25. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 26. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more
  • 27. Available modules ● Provides lightweight, throwaway instances of common databases, Selenium web browsers, and more ● Can start anything else that can run in a Docker container Whale by Artzgeo on Noun Project
  • 28. And in the cloud! Testcontainers Cloud SaaS Platform (beta) https:/ /testcontainers.cloud Photo by Engin Akyurt on Unsplash Whale by Artzgeo on Noun Project X
  • 29. Why Testcontainers? Where to use them? ● Prod-like systems: ● Easier instantiation of disposable services that lack an in-memory option ● Test against any application that can run as a container ● Integration testing: ● Data access layer integration ● Application integration ● Browser-based acceptance
  • 31. package org.testcontainers.junit.jupiter; import ... class TestcontainersExtension implements BeforeEachCallback, BeforeAllCallback, AfterEachCallback, AfterAllCallback, ExecutionCondition, TestInstancePostProcessor { @Testcontainers (JUnit 5) JUnit5 Extension - intercepts JUnit lifecycle events and manages container lifecycles @Testcontainers public class MyIntegrationTests { @Container // In JUnit 4, use @Rule/@ClassRule static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres"); ... @ExtendWith({TestcontainersExtension.class})
  • 32. @Container (JUnit 5) / @Rule (JUnit 4) @Testcontainers public class MyIntegrationTests { @Container // In JUnit 4, use @Rule/@ClassRule PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres"); ... Flags TestcontainersExtension about a container to manage ● New container is started/stopped for every test ● Declare as static to re-use the same container
  • 33. JUnit Test Lifecycle & Testcontainer Callbacks BeforeAllCallback BeforeEachCallback AfterAllCallback AfterEachCallback ExecutionCondition TestInstancePostProcessor
  • 34. JUnit Test Lifecycle @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } }
  • 35. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. No testcontainers default action in @BeforeAll Test 1
  • 36. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 No testcontainers action in Constructor Test 1
  • 37. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 @BeforeEach, Test1: Connect to docker Start ryuk Check system Start container Execute BeforeEach method Test 1
  • 38. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 No testcontainers action in @Test Test 1
  • 39. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg After Test 1 “AfterEach”, Ryuk cleans up container Test 1
  • 40. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg In Constructor. Class instance: LifeCycleTest@42d236fb Constructor creates a new class instance Test 2 Test 1
  • 41. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg In Constructor. Class instance: LifeCycleTest@42d236fb Container myRepo/myImg is starting: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 @BeforeEach, Test2: Start new container Execute BeforeEach method Test 2 Test 1
  • 42. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg In Constructor. Class instance: LifeCycleTest@42d236fb Container myRepo/myImg is starting: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @Test 2. Class instance: LifeCycleTest@42d236fb No testcontainers action in @Test Test 2 Test 1
  • 43. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg In Constructor. Class instance: LifeCycleTest@42d236fb Container myRepo/myImg is starting: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @Test 2. Class instance: LifeCycleTest@42d236fb In @AfterEach. Class instance: LifeCycleTest@42d236fb Ryuk removed container and associated volume(s): myRepo/myImg In @AfterAll. Static method. After Test 2 “AfterEach”, Ryuk cleans up container Test 2 Test 1
  • 44. @Testcontainers @Slf4j public class LifeCycleTest { @Container GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@17d88132 Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Pulling docker image: testcontainers/ryuk Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Pulling docker image: myRepo/myImg Container myRepo/myImg is starting: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @BeforeEach. Class instance: LifeCycleTest@17d88132, Container id: b1c63a2738a6131ac06dd90bc334e621099b8a9d0092cfbc8899954495bd57c5 In @Test 1. Class instance: LifeCycleTest@17d88132 In @AfterEach. Class instance: LifeCycleTest@17d88132 Ryuk removed container and associated volume(s): myRepo/myImg In Constructor. Class instance: LifeCycleTest@42d236fb Container myRepo/myImg is starting: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @BeforeEach. Class instance: LifeCycleTest@42d236fb, Container id: 20e4227f6d5366c7f6ccb2ebf09eb5666bb75d20a4c307c6026870dc0fc0d3a1 In @Test 2. Class instance: LifeCycleTest@42d236fb In @AfterEach. Class instance: LifeCycleTest@42d236fb Ryuk removed container and associated volume(s): myRepo/myImg In @AfterAll. Static method. No testcontainers default action in @AfterAll Test 2 Test 1
  • 45. @Testcontainers @Slf4j public class LifeCycleTest { @Container static GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } }
  • 46. @Testcontainers @Slf4j public class LifeCycleTest { @Container static GenericContainer container = new GenericContainer(DockerImageName.parse("myRepo/myImg")); public LifeCycleTest() { log.info("In Constructor. Class instance: ", this); } @BeforeAll public static void beforeAllMethod() { log.info("In @BeforeAll. Static method."); } @BeforeEach public void beforeEachMethod() { log.info("In @BeforeEach. Class instance: " + this + ", Container id: ", container.getContainerId()); } @Test public void test1() { log.info("In @Test 1. Class instance: ", this); } @Test public void test2() { log.info("In @Test 2. Class instance: ", this); } @AfterEach public void afterEachMethod() { log.info("In @AfterEach. Class instance: ", this); } @AfterAll public static void afterAllMethod() { log.info("In @AfterAll. Static method."); } } Found Docker environment with local Unix socket (unix:///var/run/docker.sock) Connected to docker Ryuk started - will monitor and terminate Testcontainers containers on JVM exit Checking the system... ✔ Docker server version should be at least 1.6.0 ✔ Docker environment should have more than 2GB free disk space Container myRepo/myImg is starting: 8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a In @BeforeAll. Static method. In Constructor. Class instance: LifeCycleTest@63a5d002 In @BeforeEach. Class instance: LifeCycleTest@63a5d002, Container id: 8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a In @Test 1. Class instance: LifeCycleTest@63a5d002 In @AfterEach. Class instance: LifeCycleTest@63a5d002 In Constructor. Class instance: LifeCycleTest@60e949e1 In @BeforeEach. Class instance: LifeCycleTest@60e949e1, Container id: 8d8ff20a9f25dd8b0d4cd025406bdebfa9dcf5ab637ef53b5a815d97bc739b5a In @Test 2. Class instance: LifeCycleTest@60e949e1 In @AfterEach. Class instance: LifeCycleTest@60e949e1 In @AfterAll. Static method. Ryuk removed container and associated volume(s): myRepo/myImg Container is reused across tests Test 2 Test 1
  • 47. Spring Boot ❤ Testcontainers https://github.com/danvega/reading-list
  • 48. Q&A