Nit*_*tal 8 java integration-testing unit-testing spring-boot spring-boot-test
我在网上查看了与测试相关的各种教程,Spring Boot并对测试的引用方式感到困惑。
有些文章将使用@WebMvcTest注释的控制器测试称为 as,Unit Test而有些则将其称为Integration Test. 不确定哪一个是正确的。
同样的问题适用于使用@DataJpaTest.
我在我的应用程序中编写了以下两个测试,一个用于控制器,另一个用于存储库。
在底部,我对两者都有一些疑问。请指导。
用户控制器测试.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());
}
}
Run Code Online (Sandbox Code Playgroud)
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("ab@cd.com");
entityManager.persistAndFlush(u);
// when
Optional<User> user = userRepository.findById(1L);
// then
assertTrue(user.isPresent());
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
@WebMvcTest, @DataJpaTest或@SpringBootTest决定了测试的类型(Unit或Integration)还是@MockBean在测试中的使用决定了它?UserControllerTest.java是一个单元测试,我们在userRepository这里模拟依赖关系,@MockBean private UserRepository userRepository而在UserRepositoryTest.java我们使用 @Autowired private UserRepository userRepository. 为什么 ??为什么需要spring来做单元测试?您只能使用 Mockito 来执行此操作,而无需启动 spring 上下文。在这里详细解释和讨论:https : //reflectoring.io/unit-testing-spring-boot/
在使用@MockBean 时,我也很困惑!这被认为是单元测试还是集成测试?在我看来,即使我们使用的是模拟 bean,但我们仍然在 spring 上下文中运行,对我来说这是一个集成测试(因为单元测试不需要任何 spring 上下文来运行)。Brandon 提到的同一站点将 @MockBean 视为集成测试https://www.baeldung.com/java-spring-mockito-mock-mockbean。
Brandon 回应:“集成测试不应该包含任何模拟,两种类型的测试都应该单独运行。”
如果你想测试一个从控制器开始一直到数据库的 api,但又想排除其他系统(比如 kafka 或外部微服务)怎么办?你将如何实现这一目标?你肯定需要@MockBean。这是一个集成测试,即使它模拟了 bean。
总而言之(根据我的经验以及在搜索和阅读了很多天的矛盾信息之后)。这是我的意见:
我认为最令人困惑的部分是 在问题中仅使用 spring 作为 UserControllerTest测试 api 层时(我的意思是调用 api 并确保它返回正确的状态代码和响应格式)。这被认为是单元测试还是集成测试?它不是一个单元,因为单元测试不需要 spring 上下文来运行。它实际上介于单元测试和集成测试之间。这个来源很好地解释了这个概念 https://blog.marcnuri.com/mockmvc-spring-mvc-framework/ (更具体地说是 MockMvc 独立设置)所以我认为,它可以追溯到团队在哪里放置这些测试(在单元测试文件夹中,在集成测试文件夹中,在单独的文件夹中?)还需要一个好的命名约定用于避免与同一类的纯单元测试或纯集成测试混淆。据我所知,大多数团队都会考虑这些单元测试,但我不确定这是否是最佳实践!
//unit test to call an api using MockMvc and mockito only
@RunWith(MockitoJUnitRunner.class)
public class UserControllerTest {
private MockMvc mockMvc;
@Mock
UserService userService;
@InjectMocks
UserController controllerUnderTest;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controllerUnderTest).build();
}
@Test
public void testGetUser() throws Exception {
//given:
when(userService.getUser(.......)).thenReturn(....);
//when:
String url = "http://localhost:8081/api/ ....your url";
//then:
this.mockMvc.perform(get(url)).andDo(print()).andExpect(status().isOk());
}
Run Code Online (Sandbox Code Playgroud)
}
希望有所帮助,如果有更好的意见,请告诉我,因为我为此苦苦挣扎:)
单元测试独立运行,而集成测试在执行开始之前引导 Spring Web 上下文。
单元测试
隔离运行有时需要您根据正在测试的类来模拟依赖项。通过这样做,您可以端到端地测试非常具体的测试用例,而不必担心服务或域层的开销。因此,使用 Mockito 或更具体地说,使用 Mockito.mock() 方法来模拟对象类,并且不会替换 Web 上下文中的任何对象,例如 @MockBean。
集成测试
而集成测试侧重于集成应用程序的不同层,例如数据库。关于数据库,大多数人使用内存数据库(例如 H2)来测试他们的域层/存储库。集成测试不应包含任何模拟,并且两种类型的测试应单独运行。这并不是说集成测试不能包含任何模拟,但这并不常见,因为您已经有了独立的单元测试来测试包含模拟依赖项的应用程序的各个层!
端到端测试
如果您正在从端到端测试您的应用程序,那么最好不要模拟数据以外的任何内容,并进行适当的清理。Cucumber 等测试框架非常适合端到端测试。为什么要模拟不同的层,您已经有了针对该类型测试的单元测试!
资源:https://www.baeldung.com/spring-boot-testing和 https://www.baeldung.com/java-spring-mockito-mock-mockbean
| 归档时间: |
|
| 查看次数: |
4827 次 |
| 最近记录: |