springboot mock controller和log4j 单元测试实践1

本文详细指导如何在SpringBoot项目中使用MockMvc模拟HTTP请求,以及如何通过CaptureSystemOutput验证controller的日志输出。通过实例演示如何编写单元测试,确保代码逻辑和日志一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文重点将讲述如何在单元测试中,mock controller的请求,测试controller请求,同时顺带着讲解如何在单测中测试代码日志中输出的内容。

首先,新建spring boot的项目

image.png

image.png

image.png

image.png

按照上面几张图的操作,一个简单的spring boot 项目就建立好了


上图中,我建立了一个gradle管理spring boot项目,项目的结构如下图,左侧图示。

这里要额外说一下,有gradlew / gradlew.bat的脚本,mac 或者 linux系统可以在项目的当前目录下,执行 ./gradlew build 来构建整个项目,Windows使用gradlew.bat的脚本或者在Windows的bash下同样执行 ./gradlew build 来构建整个项目

image.png

上图中,标红的部分,是一种代码风格规范约束,代码的缩进换行,统一使用 google java format。

比如,不同的人,可能使用不同的操作系统进行编程,哪怕是使用同样的操作系统,但是每个人的idea的配置都是有差异的,再加上每个人的代码风格习惯不一样,就很难在一个项目形成统一的风格,所以在项目中配置了上述的 google java format, 每个人在提交代码前执行 ./gradlew spotlessApply, 这样整个工程就按照统一的编码风格来规范代码了。


我把上面的配置贴在了下面,方便读者 ctrl + c / ctrl + v
```
id "com.diffplug.gradle.spotless" version "3.27.1"


spotless {
    java {
        target project.fileTree(project.rootDir) {
            include '**/*.java'
        }
        googleJavaFormat()
    }
}

```

打开工程中生成DemoApplication这个spring boot main的主入口文件在上面加入exclude, 排除掉spring security

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

@SpringBootApplication(
    exclude = {
      org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
    })
public class DemoApplication {

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


创建 DemoConfiguration类

```
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ComponentScan({"com.example.demo"})
@EnableAutoConfiguration
public class DemoConfiguration implements WebMvcConfigurer {}
```

spring boot  扫描包的默认规则是扫描和DemoApplication同一目录下的所有内容,因为后续,我们会创建子目录放置controller 、service等bean,所以在DemoConfiguration上指定包扫描了 com.example.demo下所有的文件,参考如下图

image.png

创建controller文件夹,在文件夹下新建一个DemoController类

```
package com.example.demo.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
@Slf4j
public class DemoController {

  @GetMapping("/log")
  public String log() {
    log.info("test print log");
    return "log";
  }
}
```

在这个Controller中,新建了一个http get请求的接口/api/log,实现内打印 test print log这句话

截止到这里,我们新建了一个spring boot项目,并且创建了一个DemoController,对外提供了get方法的/api/log接口。


打开DemoController,mac下快捷键使用 cmd + shift + T, 快速的创建单测类 DemoControllerTest,代码如下

```
package com.example.demo.controller;

import static org.junit.jupiter.api.Assertions.*;

import com.example.demo.extensions.CaptureSystemOutput;
import javax.validation.constraints.NotNull;
import org.junit.jupiter.api.Test;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest
@AutoConfigureMockMvc
@CaptureSystemOutput
class DemoControllerTest {

  @Autowired private MockMvc mockMvc;

  @Test
  void log(@NotNull CaptureSystemOutput.OutputCapture outputCapture) throws Exception {
    this.mockMvc
        .perform(
            MockMvcRequestBuilders.get("/api/log").header("key", "value").param("key", "value"))
        .andExpect(MockMvcResultMatchers.status().isOk());

    assertTrue(outputCapture.toString().contains("test print log"));
  }
}
```

我们使用spring boot内置的mockMvc来模拟浏览器请求,指定get方法的/api/log接口,这里为了演示如何模拟header和请求参数的构造,分别写了.header() .param()来模拟header和请求参数的构造

之后,我们校验的是期望接口返回是200,也就是上图中的 andExpect后的 status.isOk()的单测校验

这里,我加入了一个开源的CaptureSystemOutput的类,参考地址https://github.com/sbrannen/junit5-demo/blob/master/src/test/java/extensions/CaptureSystemOutput.java

这个类的主要用法,就是校验控制台日志输出的内容,是否是我们代码中的期望输出。

这个,也就是如何在单测中,来测试业务代码中,log日志是否正常输出打印。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值