集成测试 Spring Boot 3

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

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&lt;&gt;());
    when(personService.getAllPersons()).thenReturn(personListDto);
    mockMvc.perform(get(BASE_URL))
            .andExpect(status().isOk())
            .andExpect(content().string(&quot;{\&quot;persons\&quot;:[]}&quot;));

}

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);

示例:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyIntegrationTest {

@Autowired private TestRestTemplate restTemplate;

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

Example:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyIntegrationTest {

@Autowired private TestRestTemplate restTemplate;

@Test
publiс void myTest() {
    ResponseEntity&lt;String&gt; response = restTemplate.exchange(&quot;/api/something&quot;, HttpMethod.POST, requestEntity, String.class);
    // ...
}

For WebClient (or WebTestClient) you will need webflux.

&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-webflux&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&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测试的示例,它将实际的服务实例注入到您的控制器中。

@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&lt;&gt;());
		mockMvc.perform(get(BASE_URL))
				.andExpect(status().isOk())
				.andExpect(content().string(&quot;{\&quot;persons\&quot;:[]}&quot;));

	}
}

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:

确定