spring boot 项目的单元测试

项目开发中可能会遇到:单元测试代码覆盖率达到 XX% 的要求。因为 spring boot 提供了 test starter , 所以很多人就直接基于 @SpringBootTest 做起了所谓的单元测试。

这样做存在一些问题:

  1. 启动慢
  2. 依赖数据库,且对数据库有影响

基于 @SpringBootTest 的测试,其实是集成测试,自然也有其存在的价值的,但不应该用来做单元测试。

做单元测试,通常需要三个其础工具

  1. 测试框架 (Jnuit4 )
  2. Mock 工具(Mockit)
  3. 断言

而这些已经被 test starter 所依赖了,所以开发者不必再操心引入了。

package com.yjh.study.spring.boot.demo.service;

import com.yjh.study.spring.boot.demo.dao.UnitTestDao;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.*;
import org.springframework.test.util.ReflectionTestUtils;


class UnitTestServiceTest {

    // 要被测试的类,@InjectMocks 表示将被 @Mock 标记的对象注入到当前对象中
    @InjectMocks
    private UnitTestService unitTestService;

    // 通过动态代理生成一个假对象
    @Mock
    private UnitTestDao unitTestDao;

    // 这里想测试 mock 一个 final 类,因为使用的是 spring boot 3 成功了,早一些的板本会失败
    @Mock
    private FinalClassService finalClassService;

    @BeforeEach
    void setUp() {
        //  使 @Mock  @InjectMocks  生效;更早的板本中是通过调用 initMocks 方法
        MockitoAnnotations.openMocks(this);
    }

    @AfterEach
    void tearDown() {
    }

    @Test
    void findById() {

        // 打桩
        String param = "123";
        Mockito.doReturn(param).when(unitTestDao).findById(param);

        // 调用要测试的方法,并断言
        Assertions.assertEquals(param, unitTestService.findById(param));

        // 使用 spring 提供的工具,测试 private 方法
        String findResult1 = ReflectionTestUtils.invokeMethod(unitTestService, "find", param);
        Assertions.assertEquals(param, findResult1);

        // 对于没有打桩过的参数,方法返回 null
        String findResult2 = ReflectionTestUtils.invokeMethod(unitTestService, "find", "111");
        Assertions.assertNull(findResult2);

        // 静态方法的 mock
        try (MockedStatic<StaticMethodService> mockStatic = Mockito.mockStatic(StaticMethodService.class)) {
            mockStatic.when(() -> StaticMethodService.generate(param))
                    .thenReturn(param + param);
            Assertions.assertEquals(param + param, StaticMethodService.generate(param));
        }
    }
}

上边代码使用的 spring boot 板本 3.1.3。在 spring boot 2 中可能存在 final class 不能被 mock 的情况。解决方法:
创建文件:

src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker

文件中写入

mock-maker-inline

更多细节问题可以查 Junit 和 Mockito 的官方文档。

Junit 5 官方文档
Junit 5 中文文档

Mockito 官方文档
Mockito 中文文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值