{"id":21000,"date":"2023-04-19T05:00:00","date_gmt":"2023-04-19T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/testcontainers-docker-w-pracy-testera\/?category=hard-development"},"modified":"2023-04-19T08:53:57","modified_gmt":"2023-04-19T06:53:57","slug":"testcontainers-docker-in-a-testers-work","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/testcontainers-docker-in-a-testers-work\/","title":{"rendered":"Testcontainers \u2013 Docker in a tester&#8217;s work"},"content":{"rendered":"\n<p>Among many tools that are already available and those constantly emerging in the dynamic IT world, Testcontainers has drawn my attention already in 2022.<\/p>\n\n\n\n<p>I would like to introduce you to what challenges and problems can be solved by adding this option to your workshop. It won\u2019t be an article solely praising the tool, because \u2013 in addition to its obvious advantages \u2013 I also want to point out its disadvantages. I will, however, forewarn my final verdict \u2013 <strong>I am a Testcontainers proponent<\/strong> and have already located it in my test frameworks for good.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/9-2.png\"><img decoding=\"async\" width=\"862\" height=\"350\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/9-2.png\" alt=\"Testcontainers in a tester's work\" class=\"wp-image-20224\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/9-2.png 862w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/9-2-300x122.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/9-2-768x312.png 768w\" sizes=\"(max-width: 862px) 100vw, 862px\" \/><\/a><figcaption>Fig. 1 <a href=\"https:\/\/www.testcontainers.org\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Testcointainers in a tester\u2019s work<\/a><\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Docker <strong>for a manual tester<\/strong><\/strong><\/h2>\n\n\n\n<p>If you&#8217;ve dealt with databases, you probably recall your own effort to prepare a DB working environment &#8220;from scratch&#8221;. Even if it&#8217;s just a local environment, you need to have a DB driver and client, as well as set everything up properly, creating a valid connection string. This is especially important in case of Oracle databases.<\/p>\n\n\n\n<p>It all can be done much more efficiently using Docker. <a href=\"https:\/\/hub.docker.com\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Docker&#8217;s central image repository<\/a> contains an ever-expanding database of images, including Oracle database images. The manufacturer presents its official images, but other developers also provide their own versions. In short \u2013 <strong>we have all versions of almost any tool in one place<\/strong>.<\/p>\n\n\n\n<p>I am choosing an Oracle version, e.g. 9, represented by a Docker tag, and can apply a command that downloads the image to a local disk:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/1-3.png\"><img decoding=\"async\" width=\"497\" height=\"207\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/1-3.png\" alt=\"Download image command\" class=\"wp-image-20202\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/1-3.png 497w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/1-3-300x125.png 300w\" sizes=\"(max-width: 497px) 100vw, 497px\" \/><\/a><figcaption>Fig. 2 Download image command<\/figcaption><\/figure><\/div>\n\n\n\n<p>The benefit is significant, because what will appear on our disk in the form of a docker image [image] already contains everything we need to use the database. The next command [docker run], which will start the container, will make the database available for work.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/2-3.png\"><img decoding=\"async\" width=\"1003\" height=\"218\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/2-3.png\" alt=\"Run container command\" class=\"wp-image-20204\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/2-3.png 1003w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/2-3-300x65.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/2-3-768x167.png 768w\" sizes=\"(max-width: 1003px) 100vw, 1003px\" \/><\/a><figcaption>Fig. 3 <a href=\"https:\/\/hub.docker.com\/r\/gvenzl\/oracle-xe\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Run container command<\/a><\/figcaption><\/figure><\/div>\n\n\n\n<p>In the description of a given image, the author usually provides already prepared commands in various versions. All you need to do is run them locally in the Windows console.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Advantages and disadvantages of the solution<\/strong><\/h2>\n\n\n\n<p>I&#8217;m not saying that handling Docker is trivial, but I&#8217;m putting forward a thesis that <strong>once someone tries it, they won&#8217;t go back<\/strong> to the demanding installations and tedious configurations of desktop versions.<\/p>\n\n\n\n<p>There\u2019s also significant saving in disk space. Installation of a native tool almost always takes up much more disk space than a Docker image.<\/p>\n\n\n\n<p><strong>Downsides and inconveniences<\/strong> include the one-time installation of Docker itself. It is a console tool, but on Windows you can use Docker Desktop, which allows you to manage Docker images and containers transparently.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/3-3.png\"><img decoding=\"async\" width=\"957\" height=\"476\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/3-3.png\" alt=\"Docker desktop\" class=\"wp-image-20206\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/3-3.png 957w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/3-3-300x149.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/3-3-768x382.png 768w\" sizes=\"(max-width: 957px) 100vw, 957px\" \/><\/a><figcaption>Fig. 4 <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Docker Desktop<\/a><\/figcaption><\/figure><\/div>\n\n\n\n<p>It must also be admitted that we need to master the console commands, which will allow us to move in Docker freely. However, this is mainly a time effort, because I confidently say that <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/cli\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >free knowledge sources on the subject<\/a> available on the web are sufficient and <strong>there is no need to invest in paid trainings<\/strong> in case of a manual tester.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Docker for an automation tester and developer<\/strong><\/strong><\/h2>\n\n\n\n<p>Developers have already come to appreciate Docker and are taking full advantage of it. We launch a container with any application instantly (a matter of milliseconds), use it and close it just as quickly. When saving the state of an application doesn&#8217;t matter to us, it is completely seamless. There is also no trouble if communication is needed between the local disk and the container, e.g. by sending a file to the container or receiving a file from the container to the disk.<\/p>\n\n\n\n<p>It is also possible to run multiple containers at the same time and connect them into one network.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Testcontainers<\/strong><\/h2>\n\n\n\n<p>However, there is a challenge for testing applications that use containers, especially those based on microservice architecture. Integration testing is a phase during which we want to test the joint operation of different system components, e.g. Rest API and the database, or the microservice that produces messages for Kafka and consumes these messages along with the Kafka broker.<\/p>\n\n\n\n<p>When preparing automated integration tests for such an architecture, it is <strong>necessary to use a database container<\/strong>, e.g. PostgreSQL or a queue, e.g. Kafka. This container must be run in the code.<\/p>\n\n\n\n<p>This is where Testcontainers comes to the scene. It is a<strong> library that provides API for running Docker containers in the code<\/strong>. The tool supports the following programming languages:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Java,<\/li><li>Go,<\/li><li>.NET,<\/li><li>Python,<\/li><li>Node.js,<\/li><li>Rust.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4a.png\"><img decoding=\"async\" width=\"873\" height=\"198\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4a.png\" alt=\"Programming languages supported by Testcontainers\" class=\"wp-image-20209\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4a.png 873w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4a-300x68.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4a-768x174.png 768w\" sizes=\"(max-width: 873px) 100vw, 873px\" \/><\/a><figcaption>Fig. 5 <a href=\"https:\/\/www.testcontainers.org\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" ><a href=\"https:\/\/www.testcontainers.org\/\" class=\"ek-link\">Programming languages supported by Testcontainers<\/a><\/a><\/figcaption><\/figure><\/div>\n\n\n\n<p>The library provides automatic management of starting and closing containers as soon as the test is completed. It is an extremely &#8220;aesthetic&#8221; approach. The environment of the tested application is built relatively quickly (about 2-3 extra seconds) automatically just before the test. Then the logic of our scenarios is executed and the result returned, and finally the container disappears irretrievably.<\/p>\n\n\n\n<p>This &#8220;ephemerality&#8221; for an automation tester is extremely attractive. Testcontainers provides a mechanism for preparing test data &#8220;on the fly&#8221;. Also, the need to clean up the state after a test, for the sake of ensuring that artifacts and left-over data do not inadvertently affect subsequent executions of the same test, disappears. Here, each test run has its own &#8220;fresh&#8221; component instance, which disappears after the test, along with all its contents.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Testcontainers\/ryuk<\/strong><\/h3>\n\n\n\n<p>The object that manages closing selected containers is &#8220;<strong>testcontainers\/ryuk<\/strong>&#8220;. It always starts, even though we do not explicitly declare it in the code. It is a <strong>privileged container<\/strong> that is responsible for the correct and automatic closure of containers [automatic cleanup].<\/p>\n\n\n\n<p>This mechanism is of great importance, especially when we stop the execution of tests in a non-standard way, for example:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>an exception occurs during the scenario execution,<\/li><li>the full test environment couldn\u2019t be run because one container was missing,<\/li><li>during debugging we close the test from the IDE level.<\/li><\/ul>\n\n\n\n<p>All these and similar situations force the closure of running containers, to not leave &#8220;dead containers&#8221; in the memory.&nbsp; Although the library&#8217;s documentation allows your own <strong>ryuk<\/strong> configuration, or even disabling it, it is not recommended.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Testcontainers <strong>for JAVA language \u2013 demo<\/strong><\/strong><\/h2>\n\n\n\n<p>I will present a practical example of Testcontainers usage in a Java code. I want to use a PostgreSQL database as a component during [Controller] testing in a simple microservice. I have chosen Micronaut framework, but it would work just as well with the traditional Spring Boot.<\/p>\n\n\n\n<p>The service is a classic CRUD \u2013 it allows reading, saving, editing and deleting Actor entities to the database. It contains division into layers:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Controller,<\/li><li>Service,<\/li><li>Repository,<\/li><\/ul>\n\n\n\n<p>In Micronaut, such model class will look as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage com.example;\n\nimport io.micronaut.core.annotation.Nullable;\nimport io.micronaut.data.annotation.GeneratedValue;\nimport io.micronaut.data.annotation.MappedEntity;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport javax.persistence.Entity;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport javax.validation.constraints.NotBlank;\nimport javax.validation.constraints.Size;\n\n@Schema(description=&quot;Actor business model&quot;)\n@Entity\npublic class Actor\n {\n     @GeneratedValue @Id\n     @Nullable\n     private Long id;\n     @NotBlank @Size(max = 20)\n     private String firstName;\n     @NotBlank @Size(max = 20)\n     private String lastName;\n     @NotBlank\n     private Long rating;\n\n\/\/getters and setters\n}\n&#x5B;src\/main\/java\/model\/Actor] \n<\/pre><\/div>\n\n\n<p>I have defined DataSource in the configuration file <strong>application.ymk<\/strong> for Postgres, which looks as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\ndatasources:\n  default:\n    url: jdbc:postgresql:\/\/localhost:5432\/actor\n    driverClassName: org.postgresql.Driver\n    username: postgres\n    password: postgres\n    schema-generate: NONE\n    dialect: POSTGRES\n    schema: public\n<\/pre><\/div>\n\n\n<p>When the database with the right schema is running, everything works flawlessly. I can run my API tests written, for example, in REST-Assured. However, if I disable the database, no test will give reliable results. Testcontainers will allow me to &#8220;turn on&#8221; the missing component only for the time of running my tests.<\/p>\n\n\n\n<p>The first step is to download the dependencies to the project:<\/p>\n\n\n\n<p><strong>Maven<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n    &lt;groupId&gt;org.junit.jupiter&lt;\/groupId&gt;\n    &lt;artifactId&gt;junit-jupiter&lt;\/artifactId&gt;\n    &lt;version&gt;5.8.1&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.testcontainers&lt;\/groupId&gt;\n    &lt;artifactId&gt;testcontainers&lt;\/artifactId&gt;\n    &lt;version&gt;1.17.6&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.testcontainers&lt;\/groupId&gt;\n    &lt;artifactId&gt;junit-jupiter&lt;\/artifactId&gt;\n    &lt;version&gt;1.17.6&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n<\/pre><\/div>\n\n\n<p><strong>Gradle<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\ntestImplementation &quot;org.junit.jupiter:junit-jupiter:5.8.1&quot;\ntestImplementation &quot;org.testcontainers:testcontainers:1.17.6&quot;\ntestImplementation &quot;org.testcontainers:junit-jupiter:1.17.6&quot;\n<\/pre><\/div>\n\n\n<p>I then define the DataSource at the test level. In Micronaut, the <strong>application-test.yml<\/strong> configuration file is responsible for it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\ndatasources:\ndefault:\nurl: jdbc:tc:postgresql:latest:\/\/\/postgres?TC_INITSCRIPT=file:src\/test\/resources\/init-actor-testdata.sql?TC_DAEMON=true\n    \tdriverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver\n    \tminimum-idle: 5\n<\/pre><\/div>\n\n\n<p>Note that the url parameter is marked with <strong>tc<\/strong> \u2013 [jdbc:tc] \u2013 indicating that its operation will be handled by Testcontainers. Additionally, driverClassName also contains an indication of the org.testcontainers package.<\/p>\n\n\n\n<p>Now we can mark in the test class code that we will use Docker containers with annotation <strong>@Testcontainers<\/strong> before the class.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Testcontainers\n@MicronautTest(environments = &quot;test&quot;)\n@Slf4j\npublic class JdbcTemplateActorTest {\n}\n&#x5B;src\/test\/java\/ JdbcTemplateActorTest]\n<\/pre><\/div>\n\n\n<p>And with @Container annotation before a field, which defines the type and version of the container:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Testcontainers\n@MicronautTest(environments = &quot;test&quot;)\n@Slf4j\npublic class JdbcTemplateActorTest {\n\n    @Container\n    private static final PostgreSQLContainer&lt;?&gt; postgres = PostgresContainer.getContainerPostgres();\n\n&#x5B;src\/test\/java\/ JdbcTemplateActorTest]\n<\/pre><\/div>\n\n\n<p>The other annotations left are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>@MicronautTest(environments = &#8220;test&#8221;) \u2013 a Micronaut annotation to indicate that we will be using the Micronaut test context.<\/li><li>@Slf4j \u2013 Lombok annotation that starts the logger in a class.<\/li><\/ul>\n\n\n\n<p>The PostgreSQLContainer class provides us with proper operation of this detailed PostgreSQL container. Moreover, there is a generic class GenericContainer, which we can always use to store the object of any container:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Container\n    private static final GenericContainer&lt;?&gt; postgres = PostgresContainer.getContainerPostgres();\n\n<\/pre><\/div>\n\n\n<p>The Testcontainers library requires that we add the absolute minimum and necessary configuration of our container. After all, we have to choose which postgres image we need, define the schema name, username and password.<\/p>\n\n\n\n<p>Personally, I prefer to put such configuration not in the test class, but in a separate class responsible for postgres containers. It makes sense because postgres is not the only component we could potentially need. When Kafka, Redis or MongoDB appear, we will <strong>safely separate all these configurations<\/strong>.<\/p>\n\n\n\n<p>The code for such class might look as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npackage com.example.containers;\n\nimport org.testcontainers.containers.PostgreSQLContainer;\nimport org.testcontainers.utility.DockerImageName;\n\npublic class PostgresContainer extends PostgreSQLContainer&amp;lt;PostgresContainer&gt; {\n    private static final String MYPOSTGRESIMAGE = &quot;postgres:latest&quot; ;\n    private static final String MYTESTDATABASENAME = &quot;actor&quot;;\n    private static final String USERNAME = &quot;postgres&quot;;\n    private static final String PASSWD = &quot;postgres&quot;;\n    private static final Integer DB_PORT = 5432;\n\n    private PostgresContainer() {\n        super(DockerImageName.parse(MYPOSTGRESIMAGE));\n    }\n\n    public static PostgreSQLContainer&amp;lt;?&gt; getContainerPostgres() {\n        return new PostgreSQLContainer&amp;lt;&gt;(DockerImageName.parse(MYPOSTGRESIMAGE))\n                .withDatabaseName(MYTESTDATABASENAME)\n                .withExposedPorts(DB_PORT)\n                .withUsername(USERNAME)\n                .withPassword(PASSWD);\n    }\n}\n&#x5B;src\/test\/containers\/PostgresContainer]\n<\/pre><\/div>\n\n\n<p>The static method &#8211; getContainerPostgres() is the most relevant here. At this place with the use of multiple methods beginning with &#8220;with&#8221; we set the state of our container and ways of connecting to it.<\/p>\n\n\n\n<p>The string mode of calling these methods adds tremendous convenience:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"906\" height=\"492\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4-2.png\" alt=\"tryb \u0142a\u0144cuchowy wywo\u0142ania metody\" class=\"wp-image-20212\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4-2.png 906w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4-2-300x163.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/4-2-768x417.png 768w\" sizes=\"(max-width: 906px) 100vw, 906px\" \/><\/figure>\n\n\n\n<p>Now all that is left is to transfer the container connection details with the database to the test DataSource. Together with the Micronaut @MockBean annotation, it is very simple and in the test class can look as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Testcontainers\n@MicronautTest(environments = &quot;test&quot;)\n@Slf4j\npublic class JdbcTemplateActorTest {\n\n    @Container\n    private static final PostgreSQLContainer&lt;?&gt; postgres = PostgresContainer.getContainerPostgres();\n\n    private DataSource postgresDataSource;\n\n    private JdbcTemplate jdbcTemplate;\n\n    @Inject\n    public JdbcTemplateExampleTest(DataSource postgresDataSource) {\n        this.postgresDataSource = postgresDataSource;\n    }\n\n    @MockBean(DBConnector.class)\n    DBConnector postgresConnection() {\n        PostgresTestContainer dbConnection = new PostgresTestContainer();\n        dbConnection.setUrl(postgres.getJdbcUrl());\n        dbConnection.setUsername(postgres.getUsername());\n        dbConnection.setPasswd(postgres.getPassword());\n        return dbConnection;\n    }\n&#x5B;src\/test\/java\/ JdbcTemplateActorTest]\n<\/pre><\/div>\n\n\n<p>Visible in the class bean JdbcTemplate served me only as a connector to the database. Thanks to it we&#8217;ll know that the database will actually show up when we need it, because we&#8217;ll be able to execute our queries and receive the results.<\/p>\n\n\n\n<p>When everything is prepared I can implement two simple tests:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Test 1 &#8211; shouldGetAllActorsFromDBBasedOnTestContainers() \u2013 retrieve all the actors from the database &#8211; &#8220;SELECT * FROM actor&#8221;;<\/li><li>Test 2 &#8211; shouldGetSingleActorFromDBBasedOnTestContainers() \u2013 retrieve one actor from the database &#8211; &#8220;SELECT firstname FROM actor WHERE id=1&#8221;;<\/li><\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Test\n    void shouldGetAllActorsFromDBBasedOnTestContainers() {\n        jdbcTemplate = new JdbcTemplate(postgresDataSource);\n        await().atMost(10, TimeUnit.SECONDS)\n                .until(this::isRecordLoaded);\n\n        var dbResultsSize = this.getLoadedRecords().size();\n        var dbResults = this.getLoadedRecords();\n\n        assertThat(dbResultsSize).isEqualTo(3);\n        assertThat(dbResults.get(0).get(&quot;firstname&quot;)).isEqualTo(&quot;Brad&quot;);\n        assertThat(dbResults.get(1).get(&quot;firstname&quot;)).isEqualTo(&quot;Angelina&quot;);\n        assertThat(dbResults.get(2).get(&quot;firstname&quot;)).isEqualTo(&quot;Salma&quot;);\n    }\n\n    @Test\n    void shouldGetSingleActorFromDBBasedOnTestContainers() {\n        jdbcTemplate = new JdbcTemplate(postgresDataSource);\n        await().atMost(10, TimeUnit.SECONDS)\n                .until(this::isRecordLoaded);\n\n        var dbResultsSize = this.getLoadedRecords().size();\n        var dbResults = this.getSingleRecord();\n\n        assertThat(dbResultsSize).isEqualTo(3);\n        assertThat(dbResults).isEqualTo(&quot;Brad&quot;);\n    }\n\n    private boolean isRecordLoaded() {\n        return jdbcTemplate.queryForList(&quot;Select * from actor&quot;).size() &gt; 1;\n    }\n\n    private List&lt;Map&lt;String, Object&gt;&gt; getLoadedRecords() {\n        return jdbcTemplate.queryForList(&quot;Select * from actor&quot;);\n    }\n\n    private String getSingleRecord() {\n        return jdbcTemplate.queryForObject(&quot;Select firstname from actor where id=1&quot;, String.class);\n    }\n\n&#x5B;src\/test\/java\/ JdbcTemplateActorTest]\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>Results<\/strong><\/h3>\n\n\n\n<p>Here are the results of a test class run locally in the IDE. Note how the logs in the console clearly indicate that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Docker started,<\/li><li>the privileged Testcontainers\/ryuk container started,<\/li><li>the PostgreSQL container started.<\/li><\/ul>\n\n\n\n<p>And most importantly, the execution time of both tests is <strong>only 0.5 sec<\/strong>!<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"383\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2-1024x383.png\" alt=\"Rezultaty klasy testowej uruchomionej w lokalnej IDE\" class=\"wp-image-20214\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2-1024x383.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2-300x112.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2-768x287.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2-1536x574.png 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/5-2.png 1847w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Fig. 6 Results of a test class run in the local IDE<\/figcaption><\/figure>\n\n\n\n<p>Additionally, to confirm, I am adding a view from Docker Desktop at the time of test execution. You can clearly see that the needed containers are in the running status:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2.png\"><img decoding=\"async\" width=\"1024\" height=\"268\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2-1024x268.png\" alt=\"Widok z Docker Desktop w czasie wykonania test\u00f3w\" class=\"wp-image-20216\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2-1024x268.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2-300x78.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2-768x201.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/6-2.png 1244w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Fig. 7 View from Docker Desktop during test execution<\/figcaption><\/figure><\/div>\n\n\n\n<p>You can see how Testcontainers allowed me to implement whichever integration tests with minimal effort. The necessary components &#8220;get up&#8221; as Docker containers, and after the test is executed, the components are deleted.<\/p>\n\n\n\n<p>There is one other issue that I find extremely useful in Testcontainers. These are <strong>options (flags) that I define in the<\/strong> <strong>configuration file<\/strong> application-test.yml:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>TC_INITSCRIPT<\/li><li>TC_DAEMON<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2.png\"><img decoding=\"async\" width=\"1024\" height=\"139\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2-1024x139.png\" alt=\"Flagi definiowane w pliku konfiguracyjnym application-test.yml \" class=\"wp-image-20218\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2-1024x139.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2-300x41.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2-768x104.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/7-2.png 1514w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Fig. 8 Flags defined in the application-test.yml configuration file<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>TC_INITSCRIPT<\/strong><\/h3>\n\n\n\n<p>It is understandable that when we use a database, we would like the schema, tables and some test data necessary to execute the test to already be there. Thanks to the TC_INITSCRIPT option, we can define an SQL script, which will run as soon as the DB container is started, but before the first line of code is executed.<\/p>\n\n\n\n<p>In my demo, I used the following script, so I didn&#8217;t have to handle the contents of my PostgreSQL database in the test code:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2.png\"><img decoding=\"async\" width=\"1024\" height=\"396\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2-1024x396.png\" alt=\"Skrypt src\/test\/resources\/init-actor-testdata.sql\" class=\"wp-image-20220\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2-1024x396.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2-300x116.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2-768x297.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/8-2.png 1516w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Fig. 9 Skrypt src\/test\/resources\/init-actor-testdata.sql<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>TC_DAEMON<\/strong><\/h3>\n\n\n\n<p>In the default setting, the database container is stopped after the last connection is closed. However, there are times when we will want the container to run until it is explicitly stopped or the JVM is turned off. To do this, add the TC_DAEMON parameter to the URL, as in the graphic above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Summary<\/strong><\/h2>\n\n\n\n<p>Testcontainers is a library for handling Docker containers in the code. <strong>It is perfect<\/strong> for creating ephemeral components in automated integration tests. It also allows you to load SQL scripts in such a way that the container database is already equipped with the schema and data necessary for testing.<\/p>\n\n\n\n<p>While working with Testcontainers, I noticed <strong>two inconveniences<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>you need to have experience working with external Java libraries. Individual implementation is not trivial, as Docker itself is non-trivial. The intellectual entry threshold is therefore noticeable, but I can clearly see the effort of this library creators to make the job as simple as possible for developers,<\/li><li>after working in Testcontainers all day and running integration tests repeatedly, I notice that Docker, especially Docker Desktop on Windows OS, can consume a large amount of computer resources (RAM, CPU). Many times the containers do not &#8220;get up&#8221; and the test ends with an &#8220;Initialization error&#8221;. We can then configure a range of dedicated resources for Docker in the .wslconfig file. When the container initialization error recurs, the most effective way is to simply restart the computer.<\/li><\/ul>\n\n\n\n<p>***<br>If you are interested in the subject of Docker, we encourage you to read a series of articles prepared by our expert (PL):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/sii.pl\/blog\/docker-dla-programistow-co-to-jest\/?category=development-na-twardo&amp;tag=devops,docker,kontener&amp;category=development-na-twardo&amp;tag=devops,docker,kontener\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">Docker dla programist\u00f3w: co to jest?<\/a><\/li><li><a href=\"https:\/\/sii.pl\/blog\/docker-dla-programistow-instalacja-i-budowanie-pierwszego-srodowiska\/?category=development-na-twardo&amp;tag=devops,docker,postgresql&amp;category=development-na-twardo&amp;tag=devops,docker,postgresql\" target=\"_blank\" rel=\"noreferrer noopener\">Docker dla programist\u00f3w \u2013 budowa pierwszego \u015brodowiska. Cz\u0119\u015b\u0107 I<\/a><\/li><li><a href=\"https:\/\/sii.pl\/blog\/docker-dla-programistow-budowa-srodowiska-rozwojowego-cz-2\/?category=development-na-twardo&amp;tag=devops,docker,camunda&amp;category=development-na-twardo&amp;tag=camunda,devops,docker\" target=\"_blank\" rel=\"noreferrer noopener\">Docker dla programist\u00f3w \u2013 budowa \u015brodowiska rozwojowego. Cz\u0119\u015b\u0107 II<\/a><\/li><li><a href=\"https:\/\/sii.pl\/blog\/docker-dla-programistow-dystrybucja-aplikacji-cz-3\/?category=development-na-twardo&amp;tag=devops,docker,docker-maven-plugin&amp;category=development-na-twardo&amp;tag=devops,docker,docker-maven-plugin\" target=\"_blank\" rel=\"noreferrer noopener\">Docker dla programist\u00f3w \u2013 dystrybucja aplikacji&nbsp;<\/a><\/li><\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;21000&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;7&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 7)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Testcontainers \u2013 Docker in a tester\\u0026#039;s work&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 7)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Among many tools that are already available and those constantly emerging in the dynamic IT world, Testcontainers has drawn my &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/testcontainers-docker-in-a-testers-work\/\">Continued<\/a><\/p>\n","protected":false},"author":485,"featured_media":20228,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":10,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1321],"tags":[1679,1681,1590,1548],"class_list":["post-21000","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-testing","tag-docker-en","tag-tester-en","tag-tools","tag-programming-2"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/03\/TestContainers-docker-w-pracy-testera-.jpg","category_names":["Testing"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/21000"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/485"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=21000"}],"version-history":[{"count":1,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/21000\/revisions"}],"predecessor-version":[{"id":21002,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/21000\/revisions\/21002"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/20228"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=21000"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=21000"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=21000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}