英文:
Integration tests Spring Boot 3
问题
我有点困惑,试图理解在运行Spring Boot 3 REST API应用程序(使用Data JPA和Spring MVC)的集成测试的最佳方法是什么。对于单元测试,我使用:
@WebMvcTest
@AutoConfigureMockMvc(addFilters = false)
class PersonControllerTest {
@MockBean
private PersonService personService;
@MockBean
private SkillService skillService;
@Autowired
private MockMvc mockMvc;
@Test
void whenGetPersonListThenStatusOk() throws Exception {
PersonListDto personListDto = new PersonListDto(new ArrayList<>());
when(personService.getAllPersons()).thenReturn(personListDto);
mockMvc.perform(get(BASE_URL))
.andExpect(status().isOk())
.andExpect(content().string("{\"persons\":[]}"));
}
}
但是对于集成测试,我不知道该使用什么。我可以使用mockMvc吗(它只用于单元测试吗)?还是Webclient(据我了解,只用于响应式应用程序,需要Jetty)?
因此,目标是运行一个涉及所有应用程序层和服务器的真正HTTP请求。
英文:
I got bit confused trying to understand what the best way to run integration tests for a Spring Boot 3 rest api application (data jpa,spring mvc). For unit test I use:
@WebMvcTest
@AutoConfigureMockMvc(addFilters = false)
class PersonControllerTest {
@MockBean
private PersonService personService;
@MockBean
private SkillService skillService;
@Autowired
private MockMvc mockMvc;
@Test
void whenGetPersonListThenStatusOk() throws Exception {
PersonListDto personListDto = new PersonListDto(new ArrayList<>());
when(personService.getAllPersons()).thenReturn(personListDto);
mockMvc.perform(get(BASE_URL))
.andExpect(status().isOk())
.andExpect(content().string("{\"persons\":[]}"));
}
But for integration test I have no idea what to use. Can I use mockMvc(is it only for unittest)? or Webclient(as I understood is only for reactive app and require jetty)?
So the goal would be to run a real http request involving all application layers and server.
答案1
得分: 1
> 所以目标是运行一个涉及所有应用层和服务器的真正的http请求。
对于真正的http请求,您可以使用@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
。这将在随机空闲端口上启动您的应用程序,并自动配置TestRestTemplate。
@Autowired private TestRestTemplate restTemplate;
在测试代码中不需要指定端口(也不需要主机),因为它是预配置的。
ResponseEntity<String> response = restTemplate.exchange("/api/something", HttpMethod.POST, requestEntity, String.class);
示例:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyIntegrationTest {
@Autowired private TestRestTemplate restTemplate;
@Test
public void myTest() {
ResponseEntity<String> response = restTemplate.exchange("/api/something", HttpMethod.POST, requestEntity, String.class);
// ...
}
对于WebClient(或WebTestClient),您将需要Webflux。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
这将使它通过自动装配可用。
@Autowired WebTestClient webClient;
。尽管您应该考虑是否值得添加此依赖项仅用于WebTestClient。
英文:
> So the goal would be to run a real http request involving all application layers and server.
For real http requests you can use
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
. This will start your application on random free port and also autoconfigure TestRestTemplate.
@Autowired private TestRestTemplate restTemplate;
It is not required to specify the port (nor host) in your test code as it is preconfigured.
ResponseEntity<String> response = restTemplate.exchange("/api/something", HttpMethod.POST, requestEntity, String.class);
Example:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyIntegrationTest {
@Autowired private TestRestTemplate restTemplate;
@Test
publiс void myTest() {
ResponseEntity<String> response = restTemplate.exchange("/api/something", HttpMethod.POST, requestEntity, String.class);
// ...
}
For WebClient (or WebTestClient) you will need webflux.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
Which will also make it available through auto-wiring.
@Autowired WebTestClient webClient;
. Although you should consider if it is worth adding this dependency just for WebTestClient.
答案2
得分: 0
您已经完成了测试的99%。您缺少的关键是@WebMvcTest不会创建包含您的服务bean的完整Spring上下文。我假设您正在使用Spring 3,并且使用JUnit 5。以下是一个MockMvc测试的示例,它将实际的服务实例注入到您的控制器中。
@WebMvcTest
@ExtendWith(SpringExtension.class) // SpringExtension将启动完整的Spring上下文
public class PersonController_IT {
@Autowired
private MockMvc mockMvc;
@Test
void whenGetPersonListThenStatusOk() throws Exception {
PersonListDto personListDto = new PersonListDto(new ArrayList<>());
mockMvc.perform(get(BASE_URL))
.andExpect(status().isOk())
.andExpect(content().string("{\"persons\":[]}"));
}
}
英文:
You are 99% of the way there with the test you have. The key that you're missing is that @WebMvcTest will not create the full spring context that contains your service beans. I will assume that you're on Junit5, given that you're using Spring 3. Here's an example of a MockMvc test that will inject actual service instances into your controller.
@WebMvcTest
@ExtendWith(SpringExtension.class) // SpringExtension will spin up the full Spring context
public class PersonController_IT {
@Autowired
private MockMvc mockMvc;
@Test
void whenGetPersonListThenStatusOk() throws Exception {
PersonListDto personListDto = new PersonListDto(new ArrayList<>());
mockMvc.perform(get(BASE_URL))
.andExpect(status().isOk())
.andExpect(content().string("{\"persons\":[]}"));
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论