使用 MockMvc 测试 Spring Boot 应用程序

x33g5p2x  于2022-09-29 转载在 Spring  
字(5.2k)|赞(0)|评价(0)|浏览(386)

在本教程中,我们将学习如何将 unit testing 添加到我们在本教程中讨论的基本 Spring Boot 应用程序中使用 SpringBoot 和 JPA 教程

本教程的起点将是一个 Web 应用程序的基本模板,其中包括 web、data-jpa、h2 和 thymeleaf 依赖项:

$ spring init -dweb,data-jpa,h2,thymeleaf   samplewebapp

我们的项目结构如下所示:

~/springboot:$ tree samplewebapp/
samplewebapp/
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── samplewebapp
    │   │               └── DemoApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── com
                └── example
                    └── samplewebapp
                        └── DemoApplicationTests.java

在这个项目中,已经有一个 Tester 类,其中包含一个最小的 Test :

package com.example.samplewebapp;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
  @Test
  public void contextLoads() {}
}

以上是一个示例默认测试类。让我们检查一下:

@RunWith(SpringRunner.class) :此注解是 JUnit 库的自定义扩展,它将调用它所引用的类(SpringRunner.class)

@SpringBootTest 注释告诉 Spring Boot 去寻找一个主配置类(例如一个带有 @SpringBootApplication 的配置类),并使用它来启动一个 Spring 应用程序上下文

@Test:这是一个标准的 JUnit 测试注解,将在测试开始时执行该方法。您可以有一种或多种方法。如果您有多个带有该注释的方法,则不能保证它们将按该顺序执行。为此,您需要在类中添加 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 注释。

此外,需要注意的一件事是 Spring initializr 已经为您提供了在项目中运行测试所需的库:

<?xml version="1.0" encoding="UTF-8"?><project>
   <dependency>
       	
      <groupId>org.springframework.boot</groupId>
       	
      <artifactId>spring-boot-starter-test</artifactId>
       	
      <scope>test</scope>
       
   </dependency>
</project>

您可以在 IDE 或命令行(mvn testgradle test)上运行此测试,它应该会通过。

使用 MockMVC 进行测试

测试 Spring Boot 应用程序主要有两种策略:您可以使用 MockMVC 方法编写 Controller 测试,或者使用 RestTemplate。第一个策略 (MockMVC) 将在此处显示,如果您想编写 ***real***Unit Test 代码,它应该是您的选择。另一方面,如果您打算编写集成测试,则应使用 RestTemplate 策略。

所以,这是我们的基本控制器:

package com.example.samplewebapp;

import java.net.URI;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

@RestController
public class PersonController {
  @Autowired private PersonRepository repository;

  @GetMapping("/all")
  public Iterable<Person> retrieveAllPersons() {
    return repository.findAll();
  }

  @GetMapping("/person/{id}")
  public Person retrieveStudent(@PathVariable long id) {
    Optional<Person> person = repository.findById(id);
    if (!person.isPresent()) throw new RuntimeException("id-" + id);
    return person.get();
  }

  @PostMapping("/add")
  public ResponseEntity<Object> createStudent(@RequestBody Person person) {
    person = repository.save(person);
    URI location =
        ServletUriComponentsBuilder.fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(person.getId())
            .toUri();
    return ResponseEntity.created(location).build();
  }
}

我们现在将使用 MockMVC 编写一个最小的测试类:

package com.example.samplewebapp;

import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import com.fasterxml.jackson.databind.ObjectMapper;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class DemoApplicationTests {
  @Autowired private MockMvc mvc;

  @Test
  public void checkAll() throws Exception {
    mvc.perform(get("/all").contentType(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$[0].name", is("Jack")));
  }

  @Test
  public void findById() throws Exception {
    mvc.perform(get("/person/{id}", 1))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$.id", is(1)))
        .andExpect(jsonPath("$.name", is("Jack")));
  }

  @Test
  public void add() throws Exception {
    Person user = new Person("Mark", "Stark");
    mvc.perform(post("/add").contentType(MediaType.APPLICATION_JSON).content(asJsonString(user)))
        .andExpect(status().isCreated());
  }

  public static String asJsonString(final Object obj) {
    try {
      return new ObjectMapper().writeValueAsString(obj);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}

在此示例中,我们使用注释 @AutoConfigureMockMvc。此注解告诉 SpringRunner 配置将用于进行 REST 调用的 MockMvc 实例。 MockMvc 允许我们测试我们的 @RestController 类,而无需启动 Web 服务器。

然后我们使用类 MockMVC 的方法 perform 来执行实际的 REST 调用。您可以在 IDE Run As > JUnitTest 中运行上述测试,也可以使用命令行中的“spring test”运行上述测试:

相关文章

微信公众号

最新文章

更多