【springboot单元测试,集成测试】

本文介绍一下SpringBoot中的测试方法

集成测试

@SpringBootTest

一个普通的web api

java 复制代码
@RequestMapping
@RestController
public class HelloController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping(value = "/api/hi")
    public Map<String,Object> hello() {

        String baiduRes = restTemplate.getForObject("https://www.baidu.com", String.class);
        Map<String, Object> res = new HashMap<>();
        res.put("status", "中");
        res.put("msg", baiduRes);
        return res;
    }
}

测试类:

java 复制代码
package xyz.bliu.sptest;


import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
public class ControllerTest02 {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    MockMvc mockMvc;

    @Test
    public void restTemplateShouldNotNull() {
        assertThat(restTemplate).isNotNull();
    }

    @Test
    public void testGetRequest() throws Exception {

        mockMvc.perform(get("/api/hi"))
               .andExpect(status().isOk())
               .andDo(print());
    }
}

使用mockMvc好处是不会启动真实的web服务

当然你可以使用@SpingBootTest 并且注入一个RestTemplate来做真实的请求

假如希望仅仅测试controller层时, 可以使用另外一个注解

@WebMvcTest

他有一个参数可以指定测试的controller

java 复制代码
package xyz.bliu.sptest;


import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;
import xyz.bliu.sptest.controller.HelloController;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;

@WebMvcTest(controllers = HelloController.class)
public class ControllerTest01 {


    @Autowired
    MockMvc mockMvc;

    @MockBean
    RestTemplate restTemplate;

    @Test
    public void helloShouldOK() throws Exception {

        when(restTemplate.getForObject("https://www.baidu.com", String.class)).thenReturn("haha");

        assertThat(mockMvc).isNotNull();
        mockMvc.perform(get("/api/hi").header("kk", "v1")
                        .header("Content-Type", "application/json"))
                .andDo(print())
                .andExpect(content().contentType("application/json"))
                .andExpect(content().json("{'status':'中', 'msg':'haha'}"));
    }


    @Test
    public void restTemplateShouldBeNull() {
        assertThat(restTemplate).isNull();
    }
}

这样仅会加载指定的controller和一些web层的东西不会加载其他Bean

假如这个controller中依赖其他的bean怎么办呢?

答案是需要使用@MockBean去Mock依赖的行为

例如我这里的处理

java 复制代码
 @MockBean
 RestTemplate restTemplate;

 when(restTemplate.getForObject("https://www.baidu.com", String.class)).thenReturn("haha");

其实就是说当调用restTemplate.getForObject("https://www.baidu.com", String.class)时,方法会返回"haha"


@WebMvcTest VS @SpringBootTest

显然当你只需要测试你的controller接收请求参数或者返回值时你可以使用@WebMvcTest, 因为它不需要加载整个application context, 因此会使你的test更快

然而当需要集成测试时则需要@SpringBootTest
并且他们是不能同时使用的

  • 另外你可能注意到了AssertJ 提供的 assertThat api非常好用,可以流式调用

  • 另外本文测试环境为spring boot 3.x 和 Junit5

    如果你使用是springboot 2.x 你可能还需要 @RunWith(SpringRuner.class) ( junit4)或者 @extendwith(springextension.class) (junit5)

当然你可以使用@SpingBootTest 并且注入一个RestTemplate来做真实的请求

java 复制代码
package xyz.bliu.sptest;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

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


    @Autowired
    RestTemplate restTemplate;

    @LocalServerPort
    int port;

    @Test
    public void testGet() {
        Map resp = restTemplate.getForObject("http://localhost:"+port+ "/api/hi", Map.class);
        assertThat(resp.get("status").toString()).isEqualTo("中");
    }
}
相关推荐
javachen__23 分钟前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
一只爱撸猫的程序猿8 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋8 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
武昌库里写JAVA10 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
Pitayafruit11 小时前
Spring AI 进阶之路03:集成RAG构建高效知识库
spring boot·后端·llm
zru_960212 小时前
Spring Boot 单元测试:@SpyBean 使用教程
spring boot·单元测试·log4j
甄超锋12 小时前
Java Maven更换国内源
java·开发语言·spring boot·spring·spring cloud·tomcat·maven
还是鼠鼠13 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
舒一笑17 小时前
Started TttttApplication in 0.257 seconds (没有 Web 依赖导致 JVM 正常退出)
jvm·spring boot·后端