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.引用

相关推荐
程序员云翼5 小时前
7-理财平台
java·vue.js·spring boot·后端·毕设
.生产的驴6 小时前
SpringBoot AOP切入点表达式
spring boot·后端·python
多多*6 小时前
SpringBoot 启动流程六
java·开发语言·spring boot·后端·spring
从零开始的-CodeNinja之路6 小时前
【Spring Boot】Spring AOP中的环绕通知
spring boot·后端·spring
滔滔不绝tao7 小时前
SpringBoot拦截器
java·spring boot·spring
CrazyMo_7 小时前
OpenHarmony 入门——单元测试UnitTest快速入门
单元测试·tdd
#学习的路上8 小时前
RestTemplate、MockMVC、Swagger
java·spring boot·后端
泡芙冰淇淋ya9 小时前
【spring boot项目】统一返回结果封装
java·spring boot·后端
菜鸡且互啄6911 小时前
Spring Boot Security自定义AuthenticationProvider
java·jvm·spring boot
青花锁11 小时前
Springboot实战:AI大模型+亮数据代理助力短视频时代
人工智能·spring boot·后端·短视频·亮数据