<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Rabelo Ferreira</title>
    <description>The latest articles on DEV Community by Alex Rabelo Ferreira (@alexferreiradev).</description>
    <link>https://dev.to/alexferreiradev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F763858%2F269f8fa0-aa74-46a2-b790-ced9255b6783.png</url>
      <title>DEV Community: Alex Rabelo Ferreira</title>
      <link>https://dev.to/alexferreiradev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexferreiradev"/>
    <language>en</language>
    <item>
      <title>Create fast integration tests</title>
      <dc:creator>Alex Rabelo Ferreira</dc:creator>
      <pubDate>Sat, 09 Aug 2025 02:45:55 +0000</pubDate>
      <link>https://dev.to/alexferreiradev/create-fast-integration-tests-52pa</link>
      <guid>https://dev.to/alexferreiradev/create-fast-integration-tests-52pa</guid>
      <description>&lt;p&gt;The developers need to create tests to achieve better quality for systems. There are some challenges to creating tests. The developers need to know the libraries and frameworks for testing. The company needs to create an environment like production. Using Testcontainers, you can create an environment similar to production. It increases the difficulty of creating tests and can increase the pipeline time. One solution for that is to create tests only for system slices and not for the entire system. This article shows how Spring helps us to create these types of tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spring Tests
&lt;/h2&gt;

&lt;p&gt;Tests are one part of development that is difficult for a lot of developers. The developers need to know the library and frameworks to run the tests. The libraries help to integrate the language and the framework. The framework web mocks the dependencies for each infrastructure. So the developers tend to skip the test phase due to these challenges. Spring-Boot came to help with libraries, such as the spring-boot-tests library. The library helps developers create simple tests faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slices tests on Spring Boot
&lt;/h2&gt;

&lt;p&gt;The first Spring-Boot versions only help to create integration tests. These tests set up all the configurations of the system with Spring and waste a lot of time on pipelines. Also, it wastes a lot of computer resources to run. So, Spring-Boot 2.4 added Slices tests in the testing library. This type of test configures specific layers of an application, like the web layer (MVC layer). &lt;/p&gt;

&lt;p&gt;It does not configure the database and other infrastructures. So, the test uses fewer resources and runs faster than conventional Spring tests. Also, since the first version, the community has added new Slice Tests. The last added was for Cassandra databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slice tests Types
&lt;/h2&gt;

&lt;p&gt;There are a lot of slice tests on the Spring Boot Test library. The list of types is in the official document. The main types are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MockMVC tests for Web applications&lt;/li&gt;
&lt;li&gt;JPATest for repository&lt;/li&gt;
&lt;li&gt;AMQPTest for listeners/senders&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MockMVC Tests The Mock
&lt;/h3&gt;

&lt;p&gt;McvTest will start in the Spring only for the web application layer. It won't configure the database or other beans to test this layer. An example of a controller test is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ContextConfiguration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;SpringApplicationLight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@Import&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="nc"&gt;JacksonAutoConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LoggerBeanFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ResourceExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@WebMvcTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthorizationResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationResourceIT&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CreateAuthorizationRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestFixtures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createAuthorizationRequest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="nc"&gt;MockMvc&lt;/span&gt; &lt;span class="n"&gt;mockMvc&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt; &lt;span class="n"&gt;objectMapper&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@MockBean&lt;/span&gt; &lt;span class="nc"&gt;CreateAuthorization&lt;/span&gt; &lt;span class="n"&gt;useCase&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/authorizations"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldReturn200_whenRequestIsValid&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;authorizationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"authorizationId"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;ArgumentCaptor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CreateAuthorizationInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;captor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArgumentCaptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forClass&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CreateAuthorizationInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Mockito&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;useCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;captor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;thenReturn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorizationId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;mockMvc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;perform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objectMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeValueAsString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;))).&lt;/span&gt;&lt;span class="na"&gt;andDo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MockMvcResultHandlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;andExpect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;is2xxSuccessful&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;andExpect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$.authorizationId"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorizationId&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code uses mockMvc to create a server with the controller. It creates an object of your controller configured by the &lt;code&gt;@WebMvcTest&lt;/code&gt; annotation. After Junit initialization, Spring creates an object to inject into the field &lt;code&gt;mockMvc&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The object will create an HTTP server that receives a request and calls the controller. So, in the test method, MockMvc handles the request to the controller object. &lt;/p&gt;

&lt;p&gt;The controller will process the request and return a response object. After, MockMvc will return to us the response to make assertions. We can use MockMvc to assert the status, the body content, and others with expected values.&lt;/p&gt;

&lt;h3&gt;
  
  
  JPA Tests
&lt;/h3&gt;

&lt;p&gt;Repository tests require a database infrastructure. There is more than one repository per system. We need to create a base class shared between all the repository tests. One example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ActiveProfiles&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@DataMongoTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;excludeAutoConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;EmbeddedMongoAutoConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@AutoConfigureDataJpa&lt;/span&gt;
&lt;span class="nd"&gt;@AutoConfigureTestDatabase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AutoConfigureTestDatabase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Replace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseRepositoryIT&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DynamicPropertyConfigurableContainer&lt;/span&gt; &lt;span class="n"&gt;noSqlContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomNoSqlContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DynamicPropertyConfigurableContainer&lt;/span&gt; &lt;span class="n"&gt;sqlContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomDataBaseContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;datasourceProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt; &lt;span class="n"&gt;dynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;noSqlContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sqlContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a JPA-based class. We need this base class to create the containers to serve as databases. This is a way to create a lot of repository tests with the same setup. &lt;/p&gt;

&lt;p&gt;The class is using two libraries, one for NoSQL and the other for SQL. The &lt;code&gt;DataMongoTest&lt;/code&gt; annotation sets up the NoSQL beans. You can use embedded Mongo. We are using the Testcontainers library to create containers for us. So, we exclude the embedded configuration. &lt;/p&gt;

&lt;p&gt;We did the same for SQL. The annotation &lt;code&gt;AutoConfigureTestDatabase&lt;/code&gt; removes the embedded database. After that, you can set up the properties from each container to Spring properties. Use the &lt;code&gt;DynamicPropertySource&lt;/code&gt; annotation to set properties for each database. The Spring needs the port from the container to connect to the databases. We used the dynamic properties to set the ports.&lt;/p&gt;

&lt;p&gt;Now, we can create all the repository tests extending from this base class. An example of tests for the repository can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationRepositoryIT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRepositoryIT&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Authorization&lt;/span&gt; &lt;span class="n"&gt;authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DomainFixtures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createAuthorization&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldSaveAuthorization&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Authorization&lt;/span&gt; &lt;span class="n"&gt;savedAuth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorization&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertNotNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedAuth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test uses the repository to save an entity. The database created by TestContainers is the database container. The base configuration doesn't create any other bean. The controllers, HTTP clients, and other types are not created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rest client test
&lt;/h3&gt;

&lt;p&gt;You can test REST requests too. One way is to use the Wiremock library. It creates a web server to mock some api. The component tests will call the client REST.  Wiremock will mock the request and response of the client. You can generate any response to each scenario that you want to test. The Wiremock can be set up on a container or started a server manually. You only need to set the Spring properties for the API port with the Wiremock server port. &lt;/p&gt;

&lt;p&gt;The API client tests are like repository tests. It is common to have more than one client per system. All these tests can share the same configurations. So, we can create a base class to share these configurations among all the client tests. &lt;/p&gt;

&lt;p&gt;You can configure Wiremock using a server object or a container. The first option permits you to make more flexible requests and response mocks. The container option helps you to prepare the local test infrastructure.  This option keeps the mapping files updated. One change to the API contract will break the component tests. So, in this example, we are using a container to set up Wiremock. We need to create all the files to simulate different scenarios for the tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SpringExtension&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ContextConfiguration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;FeignAutoConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;FiegnConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@EnableFeignClients&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseContainerClientTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DynamicPropertyConfigurableContainer&lt;/span&gt; &lt;span class="no"&gt;WIREMOCK_CONTAINER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomWiremockContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;datasourceProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt; &lt;span class="n"&gt;dynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;WIREMOCK_CONTAINER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annotations used above the Base class name are to set up the dependencies common to all clients.  You can reuse a container using a static field to create the container. The Testcontainers will keep the container alive until the JVM shuts down. The method implemented set up the properties related to the container. The dynamic properties object will set up the properties for your APIs. &lt;/p&gt;

&lt;p&gt;Once you have a base class, you can create a test class for each client. The class needs to extend the base class. The methods use a similar logic. It calls the client method that will make an HTTP request to the WireMock server. The WireMock will return a response. Then the method can assert on the response object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GitHubClientTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseContainerClientTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nd"&gt;@Autowired&lt;/span&gt; 
 &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClientExample&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="n"&gt;voidshouldThrowErrorWhenClientReturn500&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-500"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="n"&gt;voidshouldThrowErrorWhenClientReturn400&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-400"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="n"&gt;voidshouldReturnOkWhenClientReturnResponse&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-200"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a disadvantage to using containers instead of the WireMock server bean. You need to create a response mock in an external directory. It needs to be accessible by the container at runtime. So, you need to re-run the test after updating the mock file. Also, we cannot create two different behaviors for a get method without parameters or headers. In cases where there are many GET methods, use the Wiremock bean instead of the container. &lt;/p&gt;

&lt;p&gt;The advantage of using static files is in the development environment. The developers can run the application locally using a Docker Compose file. The tests confirm all the mocks. So, if the developer needs to simulate some scenario for a PRD bug, they can set some values in the mock files. Also, they need to run the Wiremock container to debug the PRD scenario.&lt;/p&gt;

&lt;p&gt;But there are some scenarios that the file mapping don't cover. You can use Wiremock server bean to solve this problem. Wiremock bean is an object that the developer can change the mock stubs programatically. The developer can reuse the stubs created for container base class. The base class for this type of test will be as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  @ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
       FeignAutoConfiguration.class,
        FiegnConfiguration.class,
})
@EnableFeignClients
public classBaseServerClientTest {

    private static finalWireMockConfiguration config= WireMockConfiguration.wireMockConfig()
          .usingFilesUnderDirectory("docker");
    protected staticWireMockServer wiremockServer= newWireMockServer(config);

     @DynamicPropertySource
   static voiddatasourceProperties(DynamicPropertyRegistry dynamicPropertyRegistry) {
       wiremockServer.start();
        dynamicPropertyRegistry.add("wiremock-host", wiremockServer::baseUrl);
    }
} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The class is similar to other base class in the Spring annotations. The main difference is on Wiremock server field that use a config object. You need to use this config to set the directory of yours stubs mapping files to reuse of them. Finally, you need to set the environment variable with the base url from Wiremock server. &lt;/p&gt;

&lt;p&gt;The test is the same when using file to stub. The difference now is how to stub. You need to use wiremock server variable to create stub. You have more power to create stub. You can change the return without parameters, you can simulate to return any HTTP response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;classGitHubClientTest&lt;/span&gt; &lt;span class="n"&gt;extendsBaseServerClientTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt; &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="n"&gt;privateGitHubClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="n"&gt;voidshouldThrowErrorWhenClientReturn500&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-500"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="err"&gt;  &lt;/span&gt; &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="n"&gt;voidshouldThrowErrorWhenClientReturn400&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-400"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="err"&gt;  &lt;/span&gt; &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="n"&gt;voidshouldReturnOkWhenClientReturnResponse&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="nc"&gt;GitResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-200"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"repo-test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="n"&gt;voidshouldReturnOkWhenClientReturnAllResponse&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="n"&gt;throwsJSONException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;jsonObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newJSONObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="n"&gt;jsonObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"repo"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt; &lt;span class="n"&gt;wiremockServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stubFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;            &lt;/span&gt;&lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;urlEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/git"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;                  &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;willReturn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;okJson&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="nc"&gt;GitResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GitHubClientTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseServerClientTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;GitHubClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldThrowErrorWhenClientReturn500&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-500"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldThrowErrorWhenClientReturn400&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;FeignException&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FeignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-400"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feignException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldReturnOkWhenClientReturnResponse&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;GitResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id-to-200"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"repo-test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldReturnOkWhenClientReturnAllResponse&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;JSONException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;jsonObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;jsonObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"repo"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;wiremockServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stubFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;urlEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/git"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;willReturn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WireMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;okJson&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;GitResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRepo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using bean, you can create stubs for different scenarios; you have more power. However, the local environment can not use these stubs. So, prefer to use success scenarios with file stubs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we showed how to create integration tests with fewer resources.  We showed the power of tests by layers with the Spring Boot framework. You can talk more about tests, call me. You have a special chance to book on &lt;a href="https://calendly.com/alexferreiradev/action-to-presentation" rel="noopener noreferrer"&gt;my calendly&lt;/a&gt; this week. It will be a pleasure to help you solve your problem.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>springtest</category>
      <category>java</category>
      <category>tdd</category>
    </item>
    <item>
      <title>High System quality with Spring integration tests</title>
      <dc:creator>Alex Rabelo Ferreira</dc:creator>
      <pubDate>Fri, 29 Dec 2023 00:01:08 +0000</pubDate>
      <link>https://dev.to/alexferreiradev/high-system-quality-with-spring-integration-tests-3b53</link>
      <guid>https://dev.to/alexferreiradev/high-system-quality-with-spring-integration-tests-3b53</guid>
      <description>&lt;p&gt;A developer deals with a lot of activities by day. One of which is deploying a production application. They need to ensure the quality to deploy in production. They create a pipeline to run a set of automated tests to hold the quality. This article helps Java developers create automated tests. So you will learn how to create integration tests using Spring. If you want to use Quarkus, see this &lt;a href="https://dev.to/alexferreiradev/stop-suffering-with-tests-use-testcontainers-4m3k"&gt;article for Quarkus&lt;/a&gt;. First, we will show how to create the base classes for our tests. Next, we will show how to run an application using platforms managed by a library. Finally, we will create an integration test example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a web platform Spring
&lt;/h2&gt;

&lt;p&gt;A web system needs some platforms to work. A database is the first and the second can be a cache. A back-end developer needs to set up all these platforms to test the local system. The fastest way use the docker to run a container to each platform. Using docker compose you can run all the containers by one command. So, using docker and docker compose you can run the web system in seconds. But, when the developer needs to create integration tests, the docker-compose is not enough. In this article, we will show how to create containers for tests using a library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating infrastructure with Docker
&lt;/h3&gt;

&lt;p&gt;Docker is a tool that can help the developer to run each dependency in containers. Find more about Docker at &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker Official&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provisioning with TestContainers library
&lt;/h3&gt;

&lt;p&gt;The library &lt;code&gt;TestContainers&lt;/code&gt; creates all the environments for your tests. The library starts all containers for each platform before the test starts to run. It permits you to create any type of container using codes. You can set a lot of container configurations. You can set ports, networks, and the container's version. Find more information at &lt;a href="https://www.testcontainers.org/quickstart/junit_5_quickstart/" rel="noopener noreferrer"&gt;TestContainers quick start&lt;/a&gt;. The first step is to create a base class to create the containers. First of all, you need to add the library to your dependency management. In Gradle, you can do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.junit.jupiter:junit-jupiter:5.8.1"&lt;/span&gt;
&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.testcontainers:testcontainers:1.17.2"&lt;/span&gt;
&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.testcontainers:junit-jupiter:1.17.2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Container class
&lt;/h4&gt;

&lt;p&gt;The container class is a class that extends the &lt;code&gt;GenericContainer&lt;/code&gt; class. This class is inside the TestContainers library and has a lot of methods to set up a container. The class needs to have a constructor that receives the image name and the version of the container. Each platform required by the application needs a container class. For example, databases, message brokers, and caches, each need a container class. There are already some container classes inside the library as known databases. But, if you need a specific configuration, you need to create a new class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a integration test
&lt;/h3&gt;

&lt;p&gt;The integration test is a test that runs the application with all the dependencies. The test can be a simple test that runs a method or a test that runs a complete flow of the application. So, the developer needs to create a test that uses the web platform to simulate the real environment. After creating the container classes, you can create a base integration class. You will use this class to set up all your test changes in one place.&lt;/p&gt;

&lt;h4&gt;
  
  
  Base test class
&lt;/h4&gt;

&lt;p&gt;A base class will create all the containers and set up the connection configurations. For example, you can see below a Java class example for Spring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootTest&lt;/span&gt;
&lt;span class="nd"&gt;@ActiveProfiles&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IntegrationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PostgreSQLContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PostgreSQLContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres:13.2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RedisContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;REDIS_CONTAINER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedisContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"redis:6.2.1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
        &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;postgresProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;POSTGRES_CONTAINER:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;POSTGRES_CONTAINER:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;POSTGRES_CONTAINER:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getPassword&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
        &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;redisProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.host"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;REDIS_CONTAINER:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getHost&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.port"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;REDIS_CONTAINER:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getFirstMappedPort&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to configure in this class each platform that your application uses. You configure a database and Redis cache platforms for example. An important thing to notice is the static container field. The TestContainers library uses the same container for all the tests. The library creates a singleton container. After that, you can create your integration test class. The example below shows how to create an integration test class for a Spring application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryIT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IntegrationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldCreateUser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alex"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;isPresent&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see the containers created by the TestContainers after running the tests. The Spring will replace the connection configuration for the database. After, Spring will create the repository bean using the correct database connection. So, the test can use the repository to assert the result for each scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/alexferreiradev/tecnologias_java/tree/international-career-day-23/Spring/sample-api/src/test/java/dev/alexferreira/sampleapi/infrastructure/kafka" rel="noopener noreferrer"&gt;Github&lt;/a&gt; host this example. The versions used are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Junit: 5&lt;/li&gt;
&lt;li&gt;TestContainers: 1.17.6&lt;/li&gt;
&lt;li&gt;Java 11&lt;/li&gt;
&lt;li&gt;Spring boot: 2.5.6 &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we showed how to create integration tests with the Spring framework. We use the TestContainers library to create all platforms required by the application. The community created a lot of repositories to share binds to other languages. See more in the &lt;a href="https://github.com/testcontainers" rel="noopener noreferrer"&gt;TestContainers's Github account&lt;/a&gt;. If you like this content and want to talk more about a problem, call me. You have a special chance to book on &lt;a href="https://calendly.com/alexferreiradev/action-to-presentation" rel="noopener noreferrer"&gt;my calendly&lt;/a&gt; this week. It will be a pleasure to help you solve your problem.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>testing</category>
      <category>testcontainers</category>
    </item>
    <item>
      <title>Stop suffering with tests, use TestContainers</title>
      <dc:creator>Alex Rabelo Ferreira</dc:creator>
      <pubDate>Thu, 02 Feb 2023 21:56:25 +0000</pubDate>
      <link>https://dev.to/alexferreiradev/stop-suffering-with-tests-use-testcontainers-4m3k</link>
      <guid>https://dev.to/alexferreiradev/stop-suffering-with-tests-use-testcontainers-4m3k</guid>
      <description>&lt;p&gt;Developers need to work with two or more systems during the workday. The quality of these systems depends on the integration and unit tests. It requires a pipeline and a big infrastructure. The pipeline run tests in a server similar to the production server called staging. According to [&lt;a href="https://www.servermania.com/kb/articles/how-much-does-a-typical-home-server-cost/" rel="noopener noreferrer"&gt;1&lt;/a&gt;,&lt;a href="[https://blog.unimake.com.br/gemini/7-despesas-que-sua-empresa-vai-ter-com-um-servidor-de-backup-interno/]"&gt;2&lt;/a&gt;], the cost to maintain a server is 2k to 15k in production. It is a high cost depending on the company. The cost duplicates when needs an environment for production and another for staging. But a pipeline that runs tests in a staging environment can result in a lot of false positive errors when a dependent system is down or a team is deploying a new version. Also, a developer team can lead to other problems, the high platform amount to install, the difference between platforms' versions per developer, the difficulty to update the platform version, and the difference between platforms' versions in production and developer environments.&lt;/p&gt;

&lt;p&gt;A rest API system needs at least one database and a message broker system. But a real market system needs a cache service, and storage system and the list of platforms can increase a lot according to market requirements. So, to run locally the system, a developer needs to install all that platforms. The number can increase exponentially when has more systems. The developer needs to install different versions of each platform to each system. Another problem is that a developer can install a platform with &lt;em&gt;version x&lt;/em&gt; and another developer install &lt;em&gt;version z&lt;/em&gt;. The first developer can create a test that works in the &lt;em&gt;version x&lt;/em&gt;, but doesn't work in &lt;em&gt;version z&lt;/em&gt;. So, the second developer can not run the tests and require help to discover the error because of the difference in the versions. A similar problem is when a bug happens in production and don't happen locally because of difference in the versions. In addition, when a new developer tries to set up the developer environment, the code cloned doesn't have the version of the platforms. So, he needs to install the lasted version available to run the tests. The end of history is that a lot of tests will fail and in the worst case he won't run the system locally without the help of a senior developer.&lt;/p&gt;

&lt;p&gt;This article is to help developers to waste less money and to continue increasing the system delivery quality. We will show how can use two tools, Docker and TestContainers to decrease the cost to test systems with Java. Use Docker to provide the infrastructure to your dependencies and the TestContainers is a library that permits you to create different scenarios for your tests. Therefore, the reader will learn how to use these tools to create your test environment easily, having the lowest cost and working without difficulties with a developer team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating infrastructure with Docker
&lt;/h2&gt;

&lt;p&gt;All software needs some infrastructure like a database or a message broker. The basic process for a developer to test the software in the development stage is manually creating the environment in your workstation. Docker is a tool that can help the developer to run each dependency in containers. Find more about Docker at &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker Official&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provisioning with TestContainers library
&lt;/h2&gt;

&lt;p&gt;The library &lt;code&gt;TestContainers&lt;/code&gt; make it easy to create all the environments for your tests at the start of the test platform. It permits you to create any type of container programmatically. You can set the ports, the networks, version of the containers and can set the correct configuration for each test. Find more information at &lt;a href="https://www.testcontainers.org/quickstart/junit_5_quickstart/" rel="noopener noreferrer"&gt;TestContainers quick start&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Test Containers
&lt;/h2&gt;

&lt;p&gt;First of all, you need to add the library to your dependency management. In Gradle you can do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.junit.jupiter:junit-jupiter:5.8.1"&lt;/span&gt;
&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.testcontainers:testcontainers:1.17.2"&lt;/span&gt;
&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s2"&gt;"org.testcontainers:junit-jupiter:1.17.2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two modes to set up containers in your tests, shared container, and local container. The first type is to create and stop the container only when JVM stops and the second is to create a new container for each method test. But in both modes, you create a container for your test starting from the creation of a class to your container or set up a library that creates a container for you. You can see below an example to create a container class for Postgres:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PostgreSQLContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DockerImageName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres:13-alpine"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;asCompatibleSubstituteFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
      &lt;span class="n"&gt;withUsername&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;withPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;password&amp;gt;"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;withDatabaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;db-name&amp;gt;"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;withExposedPorts&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you can create a container for your test using this class. An observation here is the need for a new dependency that has the class &lt;code&gt;PostgreSQLContainer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;testImplementation&lt;/span&gt; &lt;span class="s1"&gt;'org.testcontainers:postgresql:1.17.6'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now look at an example test using that class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleRestIT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IntegrationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt; &lt;span class="n"&gt;postgresContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

   &lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldStartingAContainer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

      &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isRunning&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scenario is to have control of the container. There is an annotation that will inform to TestContainers what container needs to be started and stopped for each method test. You can see an example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Testcontainers&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleRestIT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IntegrationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="nd"&gt;@Container&lt;/span&gt;
   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt; &lt;span class="n"&gt;postgresContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

   &lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldStartingAContainer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// postgresContainer.start(); ------ Dont need any more&lt;/span&gt;

      &lt;span class="nc"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isRunning&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using a web platform
&lt;/h2&gt;

&lt;p&gt;But this is a test without any web platform like &lt;a href="https://quarkus.io/get-started/" rel="noopener noreferrer"&gt;Quarkus&lt;/a&gt; or &lt;a href="https://spring.io/quickstart" rel="noopener noreferrer"&gt;Spring&lt;/a&gt;. A setup of TestContainers to Quarkus for example needs some new classes. But, before we need to understand our requirements. Depending on your scenario, you will need to start and stop a container for each class of tests. In another case, you can reuse one container for all tests. For the first case, create a class that implements a &lt;code&gt;QuarkusTestResourceLifecycleManager&lt;/code&gt;. For example the class below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SharedContainerResource&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;QuarkusTestResourceLifecycleManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configureProperties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this class, you can control the creation and destruction of a container. When the Quarkus context starts, it will create the container. After, it will call the method start to get all the properties to replace these values. For example, the port to connect to the Postgres database. When the Quarkus context stops, call the method stop and we can stop the container. If we don't need a new container for each test class, you can remove the stop function and create a static field like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SharedContainerResource&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;QuarkusTestResourceLifecycleManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomPostgresContainer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_CONTAINER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configureProperties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// removed the stop function of the container. The TestContainer library will destroy automatically when the JVM stops&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that configuration, we can create a container to the context, and at the end of execution, the TestContainer library will automatically stop the container. We recommend this feature for scenarios where you have independent tests and don't need new infrastructure, like a clean database. Using this mode you can waste less time running the tests than using a local container.&lt;/p&gt;

&lt;p&gt;You can find more details in &lt;a href="https://www.testcontainers.org/quickstart/junit_5_quickstart/" rel="noopener noreferrer"&gt;TestContainers quick start&lt;/a&gt; from the official documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment
&lt;/h3&gt;

&lt;p&gt;We used the following versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TestContainers: 1.17.2&lt;/li&gt;
&lt;li&gt;Gradle: 6&lt;/li&gt;
&lt;li&gt;Docker: 20&lt;/li&gt;
&lt;li&gt;Quarkus: 1.13.6.Final&lt;/li&gt;
&lt;li&gt;Java: 11&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This example code is in this &lt;a href="https://github.com/alexferreiradev/OpenCertificate/tree/international-dev-career-day-22/backend" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we show how to create integration tests with containers to simulate any kind of environment. We also show the two modes of setting up the containers in your tests and the differences between them. Also, we gave examples to use the library TestContainers with the Quarkus platform.&lt;/p&gt;

&lt;p&gt;However, in this article, we did not cover how to use TestContainers with other web platforms like Spring. In Addition, more libraries integrate with Docker in other languages. The community created a lot of repositories in the &lt;a href="https://github.com/testcontainers" rel="noopener noreferrer"&gt;TestContainers's GitHub account&lt;/a&gt; to share binds to other languages.&lt;/p&gt;

&lt;p&gt;If you like this content and want to talk more about a problem that you are facing in your day aligned with tests, you have a special chance to book on &lt;a href="https://calendly.com/alexferreiradev/action-to-presentation" rel="noopener noreferrer"&gt;my calendly&lt;/a&gt; this week. It will be a pleasure to help you solve your problem.&lt;/p&gt;

</description>
      <category>java</category>
      <category>testcontainers</category>
      <category>testing</category>
      <category>integrationtest</category>
    </item>
    <item>
      <title>Don't discover bugs in production, use unit tests</title>
      <dc:creator>Alex Rabelo Ferreira</dc:creator>
      <pubDate>Thu, 31 Mar 2022 23:53:13 +0000</pubDate>
      <link>https://dev.to/alexferreiradev/dont-discover-bugs-in-production-use-unit-tests-27b0</link>
      <guid>https://dev.to/alexferreiradev/dont-discover-bugs-in-production-use-unit-tests-27b0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cqbx614byxfgmx1ills.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cqbx614byxfgmx1ills.jpg" alt="Image to all is fine" width="340" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A bug in software development is common, but some times it can cost a lot. The most known case of a bug that cost million of dollars was the Mariner 1 spacecraft. An investigation revealed the cause. A very simple software error, the developer omitted an hyphen in a line of code. That sent an incorrect guidance signals to the spacecraft. The cost of the omission turned out to be more than $18 million at the time (about $169 million in today’s currency).&lt;/p&gt;

&lt;p&gt;So, don't lose money discovering bugs in production. Prevent it with a simple method, use tests in the development stage. Here you will learn one type of test for Java projects, and how to create and run them in during development. At the end, you will be ready to configure your project with tests. Use libraries, plan the scenarios and create the tests and mocks. Finally, you will prevent bugs in production.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Prevent bugs with Unit Test
&lt;/h2&gt;

&lt;p&gt;The most simple test is unit test. It need to be simple and test only one&lt;br&gt;
scenario in isolated way. &lt;/p&gt;
&lt;h3&gt;
  
  
  Mock
&lt;/h3&gt;

&lt;p&gt;In a unit test, the main goal is to test some behavior from one unit (a class in Java). A mock is a way to create a object that the unit that you are testing depends on. So, If you are testing a Class called &lt;code&gt;ExportToJsonService&lt;/code&gt; and this class depends on a another class called &lt;code&gt;FileService&lt;/code&gt;, you can test the &lt;code&gt;ExportToJsonService&lt;/code&gt; without instantiate the real &lt;code&gt;FileService&lt;/code&gt; implementation, you can use some library to create a Mock of &lt;code&gt;FileService&lt;/code&gt;. The mock will be a object of &lt;code&gt;FileService&lt;/code&gt;, but without any implementation of the behaviors from the real implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a unit test
&lt;/h2&gt;

&lt;p&gt;Now, you know about unit test and mocks. Before starting creating a tests, we need libraries to don't reinvent the wheel. There are two Java libraries that can help you to create unit tests in JAVA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Junit&lt;/li&gt;
&lt;li&gt;EasyMock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one is a platform that help a java developer to create tests and run in a JVM. The second is a library that help you to isolate the test creating mocks for you. In the next sessions, you will learn how to use theses libraries in development proccess.  In the end, you will find the full example of a project with theses libraries in a github repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Project example
&lt;/h3&gt;

&lt;p&gt;So, let define some project to exemplify the use of the java test libraries. This project is simple, it generates a PDF certificate to participants of an event. So, there are two features in this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a certificate in PDF format&lt;/li&gt;
&lt;li&gt;Generate a certificate metada in JSON format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we designed the project to have these classes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GenerateCertificate&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificate&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="n"&gt;pdfExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="n"&gt;jsonExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GenerateCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="n"&gt;pdfExportService&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="n"&gt;jsonExportService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pdfExportService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pdfExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jsonExportService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CertificateData&lt;/span&gt; &lt;span class="n"&gt;certificateData&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Generate Object Certificate from data&lt;/span&gt;
        &lt;span class="c1"&gt;// Export a PDF file from certificate object&lt;/span&gt;
        &lt;span class="c1"&gt;// Export a Json metadata from certificate object&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ExportService&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Certificate&lt;/span&gt; &lt;span class="n"&gt;certificate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Planning your tests
&lt;/h3&gt;

&lt;p&gt;The creation of tests start from the scenarios that you need to test. There are two types of scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Success when the input are correct&lt;/li&gt;
&lt;li&gt;Error when the input are incorrect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, the first test of GenerateCertificate is when the CertificateData is enough to generate a Certificate objetct that&lt;br&gt;
can be exported in PDF and in JSON. Moreover, the second test is when there is something in the CertificateData that&lt;br&gt;
lead to a error when try to create a certificate object.&lt;/p&gt;

&lt;p&gt;Therefore, the first test is when the certificate object passed to exportService instance are correct and the two&lt;br&gt;
instances of the exportService is called.&lt;/p&gt;
&lt;h3&gt;
  
  
  First unit test
&lt;/h3&gt;

&lt;p&gt;After plan the test, develop it with Junit and EasyMock. We can create a Test with &lt;code&gt;Junit 5&lt;/code&gt; with a Class that&lt;br&gt;
had &lt;code&gt;@Test&lt;/code&gt; above a method. So, the method annotated is the first scenario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GenerateCertificateTest&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificateTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;whenGenerateCertificate_withCertificateDataValid_thenExportCertificate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created a test for the unit. Now we need to create a instance of our unit: &lt;code&gt;GenerateCertificate&lt;/code&gt;. After, we need to call the&lt;br&gt;
method to test our scenario inside the method of the test with the correct inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.model.Certificate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.model.CertificateData&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.service.ExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.easymock.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.extension.ExtendWith&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificateTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificate&lt;/span&gt; &lt;span class="n"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;whenGenerateCertificate_withCertificateDataValid_thenExportCertificate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CertificateData&lt;/span&gt; &lt;span class="n"&gt;certificateData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CertificateData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certificateData&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After, We use the EasyMock library  to create mocks and call's verification.  So, we can create a scenario to test some code flux. See the example above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.model.Certificate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.model.CertificateData&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.alexferreira.testtechniques.example.certificate.service.ExportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.easymock.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.extension.ExtendWith&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EasyMockExtension&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificateTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;EasyMockSupport&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/*01**/&lt;/span&gt;
    &lt;span class="nd"&gt;@Mock&lt;/span&gt;
    &lt;span class="cm"&gt;/*02**/&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ExportService&lt;/span&gt; &lt;span class="n"&gt;exportService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="cm"&gt;/*03**/&lt;/span&gt;
    &lt;span class="cm"&gt;/*04**/&lt;/span&gt;
    &lt;span class="nd"&gt;@TestSubject&lt;/span&gt;
    &lt;span class="cm"&gt;/*05**/&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificate&lt;/span&gt; &lt;span class="n"&gt;generateCertificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GenerateCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/*06**/&lt;/span&gt;
    &lt;span class="cm"&gt;/*07**/&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="cm"&gt;/*08**/&lt;/span&gt;    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;whenGenerateCertificate_withCertificateDataValid_thenExportCertificate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/*09**/&lt;/span&gt;
        &lt;span class="n"&gt;exportService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exportPDFFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EasyMock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;anyObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Certificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="cm"&gt;/*10**/&lt;/span&gt;
        &lt;span class="n"&gt;replayAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="cm"&gt;/*11**/&lt;/span&gt;
        &lt;span class="cm"&gt;/*12**/&lt;/span&gt;
        &lt;span class="nc"&gt;CertificateData&lt;/span&gt; &lt;span class="n"&gt;certificateData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CertificateData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="cm"&gt;/*13**/&lt;/span&gt;
        &lt;span class="n"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certificateData&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="cm"&gt;/*14**/&lt;/span&gt;
        &lt;span class="cm"&gt;/*15**/&lt;/span&gt;
        &lt;span class="n"&gt;verifyAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test detailed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's analyse the test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;line 1 - 2: define a mock exportService. The annotation specific to create an instance without any behavior.&lt;/li&gt;
&lt;li&gt;line 4: create a instance of the unit and inject the mocks.&lt;/li&gt;
&lt;li&gt;line 5: define the object to test and inject the mocks&lt;/li&gt;
&lt;li&gt;line 7-16: define the block to test and Junit execute it&lt;/li&gt;
&lt;li&gt;line 10: call &lt;code&gt;replayAll&lt;/code&gt; to specify for EasyMock the mocks to verify after that point.&lt;/li&gt;
&lt;li&gt;line 15: call &lt;code&gt;verifyAll&lt;/code&gt; to configure EasyMock to verify all calls in all mocks created. It will throw an error when some call are not expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test will verify the calls to &lt;code&gt;generateCertificate&lt;/code&gt;. If &lt;code&gt;exportPDFFile()&lt;/code&gt; was not called, the test will fail.&lt;/p&gt;

&lt;p&gt;Therefore, the EasyMock will help you to validate the unit dependencies behaviors. You can see more features from EasyMock at the &lt;a href="https://easymock.org/user-guide.html#verification" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running a test
&lt;/h3&gt;

&lt;p&gt;So, at this point, we can run the test with maven: &lt;code&gt;mvn test&lt;/code&gt; or with gradle: &lt;code&gt;gradlew test&lt;/code&gt;. The test will fail, because we did not implement the function like the test expect. According to Test driven development (TDD), we should implement the unit in a cyclic process. You need run test, implement/fix and run test. So, the implementation is incomplete until the test had passed. Find more information about TDD &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versions used in this example
&lt;/h3&gt;

&lt;p&gt;The example used in theses tutorial is hosted&lt;br&gt;
by &lt;a href="https://github.com/alexferreiradev/tecnologias_java/tree/test-techniques/test-techniques" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. The versions used are following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Junit: 5&lt;/li&gt;
&lt;li&gt;EasyMock: 4.3&lt;/li&gt;
&lt;li&gt;Java 11&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We presented how to prevents bugs with unit tests, the libraries that you can use to create the tests and mocks. Now you can prevent bug in production.&lt;/p&gt;

&lt;p&gt;We used two libraries that are enough for a developer create unit tests to his software. But, you need to pay attention to the versions and the compatibility between them. There are another libraries, but this article is not comparing them. We is showing one example of library for each requirements to create tests.&lt;/p&gt;

&lt;p&gt;I am a Java Developer that help another Java developers to apply tests techniques in software development, so they deliver stable features faster without break things.&lt;/p&gt;

</description>
      <category>junit5</category>
      <category>easymock</category>
      <category>unittest</category>
      <category>java</category>
    </item>
  </channel>
</rss>
