Skip to content

antkorwin/junit5-integration-test-utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JUnit5 - SpringBoot - Integration test utils

Getting started

You need to add next dependencies:

<dependency>
    <groupId>com.github.antkorwin</groupId>
    <artifactId>junit5-integration-test-utils</artifactId>
    <version>0.37</version>
</dependency>

And repository:

<repositories>
	<repository>
		<id>jitpack.io</id>
		<url>https://jitpack.io</url>
	</repository>
</repositories>

DI-tests

If you need to write a test for entire context configuration:

@EnableIntegrationTests
public class DiTest {

    @Autowired
    private TestBean testBean;

    @Test
    public void testDI() throws Exception {
        assertThat(testBean).isNotNull();
        assertThat(testBean.hello()).isEqualTo("hello world");
    }
}

same as:

@SpringBootTest
@ExtendWith(SpringExtension.class)
public class DiTest {

    ...
}

Rest-API tests

When you need to test a REAST API layer, use can use the @EnableRestTests annotation:

@EnableRestTests
public class ApiTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testApi() throws Exception {
        // Arrange
        // Act
        String result = mockMvc.perform(get("/api/test"))
                               // Assert
                               .andExpect(status().isOk())
                               .andReturn().getResponse().getContentAsString();

        assertThat(result).isEqualTo("hello world");
    }
}

same as

@SpringBootTest
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
public class ApiTest {

    ...
}

JPA tests

JPA-layer

If you need to make a test only for a JPA layer, without initializing entire context of application, you can use a @EnableDataTests annotation instead of using a @EnableIntegrationTests.

Be careful, all your services and components except spring data’s(JPA repository, transaction managers, datasorces..) not load within context.

@EnableDataTests
public class RiderDataTest {

    @Autowired
    private FooRepository repository;

    @Test
    public void testCreate() throws Exception {

        assertThat(repository).isNotNull();
    }
}

the same as:

@DataJpaTest
@ExtendWith(SpringExtension.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class RiderDataTest {

    ...
}

Database Rider

In order to work with data sets based on the DbUnit, you can use a Database Rider library, for integration woth this library you can add `` annotation in your test. However you also need to run one of the context configuration because this annotation not work without running JPA context.

@EnableDataTests
@EnableRiderTests
public class RiderDataTest {

    @Autowired
    private FooRepository repository;

    @Test
    @Commit
    @DataSet(cleanBefore = true, cleanAfter = true, transactional = true)
    @ExpectedDataSet(value = "/datasets/expected.json", ignoreCols = "ID")
    public void testCreate() throws Exception {

        repository.saveAndFlush(Foo.builder()
                                   .field("tru la la..")
                                   .build());
    }
}

the same as:

@DBRider
@DataJpaTest
@ExtendWith(SpringExtension.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class RiderDataTest {

    ...
}

PostgreSQL

In order to test you native query on the real data base instead of in-memory H2, you can use a test-containers library and PostgreSQL docker container.

When you add an annotation @EnablePostgresTestContainers, testcontainers run image for the PostgreSQL in you test.

Data JPA

You can combine annotations which you need:

@EnableDataTests
@EnableRiderTests
@EnablePostgresTestContainers
public class PostgresTcDataTest {

    @Autowired
    private FooRepository repository;

    @Test
    @Commit
    @DataSet(cleanBefore = true, cleanAfter = true)
    @ExpectedDataSet(value = "/datasets/expected.json", ignoreCols = "ID")
    public void testCreate() throws Exception {

        repository.saveAndFlush(Foo.builder()
                                   .field("tru la la..")
                                   .build());
    }
}

or use a meta-annotation @PostgresDataTests for this configuration:

@PostgresDataTests
public class PostgresDataTest {
    ...
}

Integration(entire context)

In the same way you can make an integration configuration for test with postgres container:

@EnableIntegrationTests
@EnableRiderTests
@EnablePostgresTestContainers
public class PostgresTcIntegrationTest {
    ...
}

or use a meta-annotation for this configuration:

@PostgresIntegrationTests
public class PostgresIntegrationTest {
    ...
}

H2

Data JPA

@H2DataTests
public class H2DataTest {

}

Integration(entire context)

@H2IntegrationTests
public class H2DataTest {

}

MySQL

Data JPA

@MySqlDataTests
public class H2DataTest {

}

Integration(entire context)

@MySqlIntegrationTests
public class H2DataTest {

}

Run multiple embedded web servers in one test suite

If you need to run multiple embedded web servers in one test suite, for example to run different controllers in @TestConfiguration classes.

Let’s consider an example of testing pair feign in one test suite.

First test:

@EnableTestsWithEmbeddedWebServer
public class ATest {

    @Autowired
    private AFeign aFeign;

    @Test
    void testA() {
        // Arrange
        // Act
        String test = aFeign.test();
        // Assert
        assertThat(test).isEqualTo("A");
    }

    @TestConfiguration
    public static class TestConfig {

        @RestController
        @RequestMapping("test")
        public class A implements AFeign {

            @Override
            public String test() {
                return "A";
            }
        }
    }
}

Second test:

@EnableTestsWithEmbeddedWebServer
public class BTest {

    @Autowired
    private BFeign bFeign;

    @Test
    void testB() {
        // Arrange
        // Act
        String test = bFeign.test();
        // Assert
        assertThat(test).isEqualTo("B");
    }

    @TestConfiguration
    public static class TestConfig {

        @RestController
        @RequestMapping("test")
        public class B implements BFeign {

            @Override
            public String test() {
                return "B";
            }
        }
    }
}

The EnableTestsWithEmbeddedWebServer annotation provide you an ability to run these tests in one test suite without conflicts about The port may already be in use.

Each of these tests will run on a different available port.

You can look at the example of usage multiple embedded web servers here link:https://github .com/antkorwin/junit5-integration-test-utils-examples[junit5-integration-test-utils-examples]