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>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 {
...
}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 {
...
}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 {
...
}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 {
...
}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.
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 {
...
}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 {
...
}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]