Anzeige
Anzeige

Más contenido relacionado

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

Anzeige

Más de VMware Tanzu(20)

Anzeige

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.
  3. Testing is important
  4. Testing can be hard
  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
  7. INTRO
  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
  16. TESTCONTAINERS 101
  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
  30. inspiration...
  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
Anzeige