SpringBoot项目如何进行单元测试

Spring Boot 的测试类库

Spring Boot 提供了许多实用工具和注解来帮助测试应用程序,主要包括以下两个模块:

  • spring-boot-test:支持测试的核心内容。
  • spring-boot-test-autoconfigure:支持测试的自动化配置。

开发进行只要使用 spring-boot-starter-test 启动器就能引入这些 Spring Boot 测试模块,还能引入一些像 JUnit, AssertJ, Hamcrest 及其他一些有用的类库,具体如下所示:

  • JUnit:Java 应用程序单元测试标准类库。
  • Spring Test & Spring Boot Test:Spring Boot 应用程序功能集成化测试支持。
  • AssertJ:一个轻量级的断言类库。
  • Hamcrest:一个对象匹配器类库。
  • Mockito:一个Java Mock测试框架,默认支付 1.x,可以修改为 2.x。
  • JSONassert:一个用于JSON的断言库。
  • JsonPath:一个JSON操作类库。

测试 Spring Boot 应用程序

添加 Maven 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.6.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

user实体类准备

public class User {

    private Integer id;

    private String name;

    //如果作为controller的入参,必须存在空参的构造函数
    public User() {

    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

service准备

public interface UserService {

    User add(User user);

    User update(User user);

    void delete(Integer id);

    User selectByName(Integer id);

    List<User> listUser();
}

//-------------------------------------
@Service
public class UserServicempl implements UserService {

    private Map<Integer, User> userMap = new HashMap();

    @PostConstruct
    public void initUser() {
        userMap.put(1, new User(1, "张三"));
        userMap.put(2, new User(2, "李四"));
        userMap.put(3, new User(3, "王五"));
        userMap.put(4, new User(4, "刘能"));
    }

    @Override
    public User add(User user) {
        userMap.put(user.getId(), user);
        return user;
    }

    @Override
    public User update(User user) {
        userMap.put(user.getId(), user);
        return user;
    }

    @Override
    public void delete(Integer id) {
        userMap.remove(id);
    }

    @Override
    public User selectByName(Integer id) {
        return userMap.get(id);
    }

    @Override
    public List<User> listUser() {
        return new ArrayList(userMap.values());
    }
}

controller准备

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("add")
    public User add(@RequestBody User user) {
        return userService.add(user);
    }

    @PostMapping("update")
    public User update(@RequestBody User user) {
        return userService.update(user);
    }

    @PostMapping("delete/{id}")
    public void delete(@PathVariable(value = "id") Integer id) {
        userService.delete(id);
    }

    @GetMapping("selectByName")
    public User selectByName(Integer id) {
        return userService.selectByName(id);
    }

    @GetMapping("listUser")
    public List<User> listUser() {
        return userService.listUser();
    }
}

Spring Boot中单元测试类写在在src/test/java目录下,你可以手动创建具体测试类:

/**
 * 添加@SpringBootTest注解, 指定用的是哪个启动类即可
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApp.class)
public class WebSpringTest {
    

}

service单元测试

/**
 * 添加@SpringBootTest注解, 指定用的是哪个启动类即可
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApp.class)
public class WebSpringTest {

    @Autowired
    private UserService userService;

    @Test
    public void testListUser(){
        System.out.println(userService.listUser());
    }
}

简单的不能再简单了。

controller单元测试

上面只是针对Service层做测试,但是有时候需要对Controller层(API)做测试,这时候就得用到MockMvc了,你可以不必启动工程就能测试这些接口。

MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

/**
 * 添加@SpringBootTest注解, 指定用的是哪个启动类即可
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApp.class)
public class WebSpringTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mvc;

    @Before
    public void setupMockMvc() {
        mvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象
    }

    /**
     * 新增用户
     *
     * @throws Exception
     */
    @Test
    public void testAddUser() throws Exception {
        String json = "{\"id\": \"1\",\"name\":\"Spring\"}";
        mvc.perform(MockMvcRequestBuilders.post("/user/add")
                    .contentType("application/json; charset=utf-8")
                    .accept("application/json; charset=utf-8")
                    .content(json.getBytes()) //传json参数
                   )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andDo(MockMvcResultHandlers.print());
    }


    /**
     * 获取用户
     *
     * @throws Exception
     */
    @Test
    public void testGetUser() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/selectByName?id=1")
                    .contentType("application/json; charset=utf-8")
                    .accept("application/json; charset=utf-8")
                   )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.jsonPath("$.id").value("1"))
            .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("张三"))
            .andDo(MockMvcResultHandlers.print());
    }

    /**
     * 修改用户
     *
     * @throws Exception
     */
    @Test
    public void testUpdateUser() throws Exception {
        String json = "{\"id\":\"2\",\"name\":\"Spring\"}";
        mvc.perform(MockMvcRequestBuilders.post("/user/update")
                    .contentType("application/json; charset=utf-8")
                    .accept("application/json; charset=utf-8")
                    .content(json.getBytes())//传json参数
                   )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andDo(MockMvcResultHandlers.print());
    }

    /**
     * 删除用户
     *
     * @throws Exception
     */
    @Test
    public void testDeleteUser() throws Exception {
        mvc.perform(MockMvcRequestBuilders.post("/user/delete/3")
                    .contentType("application/json; charset=utf-8")
                   )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andDo(MockMvcResultHandlers.print());
    }

    /**
     * 获取用户列表
     *
     * @throws Exception
     */
    @Test
    public void testListUser() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/listUser")
                    .contentType("application/json; charset=utf-8")
                    .accept("application/json; charset=utf-8")
                   )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andDo(MockMvcResultHandlers.print());
    }

}
  • mockMvc.perform执行一个请求
  • MockMvcRequestBuilders.get(“/selectByName?id=3”)构造一个请求,Post请求就用.post方法
  • contentType("application/json; charset=utf-8") 代表发送端发送的数据格式是application/json;charset=UTF-8
  • accept(""application/json; charset=utf-8"") 代表客户端希望接受的数据类型为application/json;charset=UTF-8
  • ResultActions.andExpect添加执行完成后的断言
  • ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看请求的状态响应码是否为200如果不是则抛异常,测试不通过
  • andExpect(MockMvcResultMatchers.jsonPath(“$.name”).value("张三")) 这里jsonPath用来获取name字段比对是否为张三,不是就测试不通过
  • ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息

测试类库的API

org.junit.Assert

断言,里面的方法基本都是静态方法。要使用的时候直接使用具体的方法即可。

assertSame("1", "2");

常用注解

junit的注解参考:单元测试Junit

SpringBoot test 注解参考:Spring Boot Test

 

posted @ 2022-01-21 09:13  残城碎梦  阅读(871)  评论(0编辑  收藏  举报