Spring单元测试+Mockito

一,背景

单元测试基本上是开发逃不过的一个工作内容,虽然往往因为过于无聊,或者过于麻烦,而停止于项目的迭代之中,不了了之了。其实不是开发们懒,而是上头要求的测试覆盖率高,但是又没有好用的工具,导致工作积压,最后只能舍弃掉这部分。

最近发现Spring+junit+mockito很好用,特别是对于DDD架构的项目,可以针对特定的代码层做单元测试,贼好用。

二,环境准备

1,首先是在spring环境下,引入mockito和junit
XML 复制代码
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <scope>test</scope>
</dependency>
2,使用mockito

1,使用 `@ExtendWith(MockitoExtension.class)` 注解让 junit 使用 Mockito 环境启动单元测试,这样 `@Mock` 和 `InjectMocks` 注解才会生效。

2,使用 `@Mock` 注解来 mock 一个对象,方便后续控制这个对象的行为。

3,使用 `@InjectMocks` 注解来标注一个对象(注意,对象的类型是具体的实现类,而不是接口),junit 会自动将标有 `@Mock` 注解的对象按需注入其中。

XML 复制代码
@ExtendWith(MockitoExtension.class)
class JunitPracticeTest {

    @Mock
    private JunitGateway junitGateway;
    @Mock
    private JunitMapper junitMapper;

    @InjectMocks
    private JunitServiceImpl junitService;

    @BeforeAll
    static void setup() {
        MockStaticUtil.mockStatic(BeanUtil.class);
    }

    @Test
    void testAdd() {
        when(BeanUtil.getBean(JunitGateway.class)).thenReturn(junitGateway);

		// ...
    }
}
3,覆盖率检测
XML 复制代码
<build>
      <plugins>
          <plugin>
              <groupId>org.jacoco</groupId>
              <artifactId>jacoco-maven-plugin</artifactId>
              <!-- 这里配置的include和exclude是对整个聚合报告生效的 -->
              <configuration>
                  <includes>
                      <!-- 仅统计app层和domain层的特定类 -->
                      <include>com/spice/junit/service/**/*</include>
                      <include>com/spice/junit/**/*DO.class</include>
                  </includes>
                  <excludes>
                      <!-- 排除这个特殊类,它是infrastructure层的一个类 -->
                      <exclude>com/spice/junit/service/RedisService.class</exclude>
                  </excludes>
              </configuration>
              <executions>
                  <execution>
                      <id>pre-test</id>
                      <goals>
                          <goal>prepare-agent</goal>
                      </goals>
                  </execution>
                  <execution>
                      <id>post-test</id>
                      <phase>test</phase>
                      <goals>
                          <!-- 在app模块中聚合jacoco的报告 -->
                          <goal>report-aggregate</goal>
                      </goals>
                      <configuration>
                          <!-- 配置在聚合报告中包含本模块(risk-app模块) -->
                          <includeCurrentProject>true</includeCurrentProject>
                      </configuration>
                  </execution>
              </executions>
          </plugin>
      </plugins>
  </build>

三,实战

1,新建测试类

idea中在类里ctrl+shift+T

注意:只有public方法才能生成单元测试方法,也只有public方法才需要单元测试。

2,添加注解和注入业务类里依赖的Bean

原业务类:

单元测试类:

将原业务类依赖的mapper注入到单元测试类。 将自己的实现类也注入到单元测试类。 下面的例子中还把BeanUtil这个静态的工具类先mock了,因为后面会用到,各种工具类都可以这样来mock。

3,根据原业务类方法里的逻辑写单元测试用例
4,redis等中间件都可以mock
5,捕获自定义异常
相关推荐
海南java第二人7 分钟前
深入剖析AQS:Java并发编程的核心基石与底层实现原理
java
趁月色小酌***7 分钟前
JAVA 知识点总结3
java·开发语言·python
阿拉斯攀登12 分钟前
设计模式:Spring MVC 中命令模式的核心映射与设计逻辑
spring·设计模式·mvc·命令模式
fufu031112 分钟前
Linux环境下的C语言编程(五十二)
java·linux·c语言
BD_Marathon20 分钟前
Spring是什么
java·后端·spring
我命由我1234522 分钟前
Android 消息机制 - Looper(Looper 静态方法、Looper 静态方法注意事项、Looper 实例方法、Looper 实例方法注意事项)
android·java·android studio·安卓·android jetpack·android-studio·android runtime
月明长歌25 分钟前
【码道初阶】Leetcode138:随机链表的复制:用 HashMap 做深拷贝的标准解法
java·数据结构·算法·leetcode·链表·哈希算法
.简.简.单.单.28 分钟前
Design Patterns In Modern C++ 中文版翻译 第八章 组合
java·c++·设计模式
七夜zippoe40 分钟前
Spring MVC请求处理流程源码分析与DispatcherServlet核心逻辑
java·spring·mvc·过滤器·拦截器
笙枫42 分钟前
Agent 进阶设计:状态管理、中间件与多Agent协作
java·服务器·python·ai·中间件