集成测试 Spring Boot 3

huangapple go评论88阅读模式
英文:

Integration tests Spring Boot 3

问题

我有点困惑,试图理解在运行Spring Boot 3 REST API应用程序(使用Data JPA和Spring MVC)的集成测试的最佳方法是什么。对于单元测试,我使用:

  1. @WebMvcTest
  2. @AutoConfigureMockMvc(addFilters = false)
  3. class PersonControllerTest {
  4. @MockBean
  5. private PersonService personService;
  6. @MockBean
  7. private SkillService skillService;
  8. @Autowired
  9. private MockMvc mockMvc;
  10. @Test
  11. void whenGetPersonListThenStatusOk() throws Exception {
  12. PersonListDto personListDto = new PersonListDto(new ArrayList<>());
  13. when(personService.getAllPersons()).thenReturn(personListDto);
  14. mockMvc.perform(get(BASE_URL))
  15. .andExpect(status().isOk())
  16. .andExpect(content().string("{\"persons\":[]}"));
  17. }
  18. }

但是对于集成测试,我不知道该使用什么。我可以使用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:

  1. @WebMvcTest
  2. @AutoConfigureMockMvc(addFilters = false)
  3. class PersonControllerTest {
  4. @MockBean
  5. private PersonService personService;
  6. @MockBean
  7. private SkillService skillService;
  8. @Autowired
  9. private MockMvc mockMvc;
  10. @Test
  11. void whenGetPersonListThenStatusOk() throws Exception {
  12. PersonListDto personListDto = new PersonListDto(new ArrayList&lt;&gt;());
  13. when(personService.getAllPersons()).thenReturn(personListDto);
  14. mockMvc.perform(get(BASE_URL))
  15. .andExpect(status().isOk())
  16. .andExpect(content().string(&quot;{\&quot;persons\&quot;:[]}&quot;));
  17. }

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&lt;String&gt; response = restTemplate.exchange(&quot;/api/something&quot;, HttpMethod.POST, requestEntity, String.class);

示例:

  1. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  2. public class MyIntegrationTest {
  3. @Autowired private TestRestTemplate restTemplate;
  4. @Test
  5. public void myTest() {
  6. ResponseEntity&lt;String&gt; response = restTemplate.exchange(&quot;/api/something&quot;, HttpMethod.POST, requestEntity, String.class);
  7. // ...
  8. }

对于WebClient(或WebTestClient),您将需要Webflux。

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-webflux</artifactId>
  4. <scope>test</scope>
  5. </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&lt;String&gt; response = restTemplate.exchange(&quot;/api/something&quot;, HttpMethod.POST, requestEntity, String.class);

Example:

  1. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  2. public class MyIntegrationTest {
  3. @Autowired private TestRestTemplate restTemplate;
  4. @Test
  5. publiс void myTest() {
  6. ResponseEntity&lt;String&gt; response = restTemplate.exchange(&quot;/api/something&quot;, HttpMethod.POST, requestEntity, String.class);
  7. // ...
  8. }

For WebClient (or WebTestClient) you will need webflux.

  1. &lt;dependency&gt;
  2. &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  3. &lt;artifactId&gt;spring-boot-starter-webflux&lt;/artifactId&gt;
  4. &lt;scope&gt;test&lt;/scope&gt;
  5. &lt;/dependency&gt;

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测试的示例,它将实际的服务实例注入到您的控制器中。

  1. @WebMvcTest
  2. @ExtendWith(SpringExtension.class) // SpringExtension将启动完整的Spring上下文
  3. public class PersonController_IT {
  4. @Autowired
  5. private MockMvc mockMvc;
  6. @Test
  7. void whenGetPersonListThenStatusOk() throws Exception {
  8. PersonListDto personListDto = new PersonListDto(new ArrayList<>());
  9. mockMvc.perform(get(BASE_URL))
  10. .andExpect(status().isOk())
  11. .andExpect(content().string("{\"persons\":[]}"));
  12. }
  13. }
英文:

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.

  1. @WebMvcTest
  2. @ExtendWith(SpringExtension.class) // SpringExtension will spin up the full Spring context
  3. public class PersonController_IT {
  4. @Autowired
  5. private MockMvc mockMvc;
  6. @Test
  7. void whenGetPersonListThenStatusOk() throws Exception {
  8. PersonListDto personListDto = new PersonListDto(new ArrayList&lt;&gt;());
  9. mockMvc.perform(get(BASE_URL))
  10. .andExpect(status().isOk())
  11. .andExpect(content().string(&quot;{\&quot;persons\&quot;:[]}&quot;));
  12. }
  13. }

huangapple
  • 本文由 发表于 2023年6月5日 21:29:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76406928.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定