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]