I looked various tutorial online related to testing in Spring Boot
and got confused by the way the tests were referred.
Some articles refer to controller tests that use @WebMvcTest
annotation as Unit Test
whereas some refer it as Integration Test
. Not sure which one is correct.
Same questions applies to Repository layer test with @DataJpaTest
.
I have following two tests written in my application, one for the controller and another one for the repository.
At the bottom I have some questions regarding both. Please guide.
UserControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserRepository userRepository;
@Test
public void signUp() throws Exception {
this.mockMvc.perform(get("/signup")).andExpect(status().isOk());
}
}
UserRepositoryTest.java
@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@Test
public void whenFindByName_thenReturnEmployee() {
// given
User u = new User();
u.setName("ab");
u.setEmail("[email protected]");
entityManager.persistAndFlush(u);
// when
Optional<User> user = userRepository.findById(1L);
// then
assertTrue(user.isPresent());
}
}
My questions are:
- Does the annotation
@WebMvcTest, @DataJpaTest
or@SpringBootTest
determines the type of test (Unit
orIntegration
) or is it the use of@MockBean
within the test that determines it? - Assuming that
UserControllerTest.java
is a Unit test we are mocking theuserRepository
dependency here with@MockBean private UserRepository userRepository
whereas inUserRepositoryTest.java
we are autowiring it with@Autowired private UserRepository userRepository
. Why ??
The primary difference between unit tests and integration tests using Spring Boot, is that unit tests can run in isolation while integration tests will bootstrap Spring context before execution starts.
Running in isolation requires that you mock your dependencies based on the controller you are testing. By doing this, you're allowing yourself to test very specific test cases end-to-end without having to worry about the overhead of a database or a service. Hence, using the annotation @MockBean.
Whereas, integration testing focuses on integrating different layers of the application such as the database. Most people utilize an in memory database such as H2 to test their repositories. Integration tests should not contain any mocking and both types of testing should be run separately.