Spring Boot单元测试快速入门Demo

1.test介绍

软件测试是一个应用软件质量的保证。开发者开发接口往往忽视接口单元测试。如果会Mock单元测试,那么你的bug量将会大大降低。spring提供test测试模块。整体上,Spring Boot Test支持的测试种类,大致可以分为如下三类:

  • 单元测试:一般面向方法,编写一般业务代码时,测试成本较大。涉及到的注解有@Test。
  • 切片测试:一般面向难于测试的边界功能,介于单元测试和功能测试之间。涉及到的注解有@RunWith @WebMvcTest等。
  • 功能测试:一般面向某个完整的业务功能,同时也可以使用切面测试中的mock能力,推荐使用。涉及到的注解有@RunWith @SpringBootTest等。

功能测试过程中的几个关键要素及支撑方式如下:

  • 测试运行环境:通过@RunWith 和 @SpringBootTest启动spring容器。
  • mock能力:Mockito提供了强大mock功能。
  • 断言能力:AssertJ、Hamcrest、JsonPath提供了强大的断言能力。

2.代码工程

实验目的:验证cotroller和service层逻辑

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>test</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

配置文件

yaml 复制代码
server:
  port: 8088
  username: default

server:
  port: 8088
  username: dev

cotroller

typescript 复制代码
package com.et.test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
public class HelloWorldController {
    @RequestMapping("/hello")
    @ResponseBody
    public Map<String, Object> showHelloWorld(){
        Map<String, Object> map = new HashMap<>();
        map.put("msg", "HelloWorld");
        return map;
    }
}

service

kotlin 复制代码
package com.et.test.service;

import org.springframework.stereotype.Service;

/**
 * @ClassName UserService
 * @Description TODO
 * @Author liuhaihua
 * @Date 2024/4/4 13:13
 * @Version 1.0
 */
public interface UserService {
   public   String getUserName();
}

package com.et.test.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author liuhaihua
 * @Date 2024/4/4 13:16
 * @Version 1.0
 */
@Service
public class UserServiceImpl implements UserService{
   @Value("${server.username}")
   private String username;
   @Override
   public String getUserName() {
      return username;
   }
}

DemoApplication.java

typescript 复制代码
package com.et.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

3.测试

验证环境绑定

kotlin 复制代码
@ActiveProfiles("dev")

可以切换不同的环境,在同的环境上测试

验证controller功能

scss 复制代码
@Test
public void bookApiTest() throws Exception {

   // mockbean start
   userServiceMockBean();
   // mockbean end
   String expect = "{\"msg\":\"HelloWorld\"}";
   mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
         .andExpect(MockMvcResultMatchers.content().json(expect))
         .andDo(MockMvcResultHandlers.print());
   // mockbean reset
}

验证service功能

csharp 复制代码
  @Test
  public void execute() {
      userServiceMockBean();
      log.info("username:"+userService.getUserName());
      Assertions.assertThat(userService.getUserName().equals("mockname"));

  }

下面是完整的测试代码,感兴趣的可以去测试一下

java 复制代码
package com.et.test;

import com.et.test.service.UserService;
import org.assertj.core.api.Assertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import javax.annotation.Resource;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
@ActiveProfiles("dev")
@AutoConfigureMockMvc
public class DemoTests {
    private Logger log = LoggerFactory.getLogger(getClass());
   @Resource
   private MockMvc mockMvc;
   //@Autowired
   @MockBean
   UserService userService;
    @Before
    public void before()  {
        log.info("init some data");
    }
    @After
    public void after(){
        log.info("clean some data");
    }
    @Test
    public void execute() {
      userServiceMockBean();
        log.info("username:"+userService.getUserName());
      Assertions.assertThat(userService.getUserName().equals("mockname"));

    }
   @Test
   public void bookApiTest() throws Exception {

      // mockbean start
      userServiceMockBean();
      // mockbean end
      String expect = "{\"msg\":\"HelloWorld\"}";
      mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
            .andExpect(MockMvcResultMatchers.content().json(expect))
            .andDo(MockMvcResultHandlers.print());
      // mockbean reset
   }

   public void userServiceMockBean() {
      BDDMockito.given(userService.getUserName()).willReturn("mockname");
   }

}

4.引用

相关推荐
JH30739 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
qq_124987075312 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_12 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
2301_8187320612 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
汤姆yu16 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶16 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip17 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
JavaGuide17 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot
figo10tf18 小时前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
zhangyi_viva18 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端