当前位置: 首页 > article >正文

Spring编写单元测试的工具介绍:JUnit、Mockito、AssertJ

背景:

在Spring应用程序中,想要通过代码走查做好测试左移,单元测试是确保代码质量和功能正确性的关键。除了我们常用的TestNG外,本次介绍一下其他常见的单元测试工具: JUnit、Mockito、AssertJ,来提高我们做白盒测试的效率。

一、引入依赖

在Maven项目中,我们通过添加以下依赖来引入使用

1、JUnit

JUnit是最常用的Java单元测试框架之一,它提供了丰富的API来编写和组织测试用例。

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.1</version>
    <scope>test</scope>
</dependency>

2、Mockito

Mockito允许我们创建模拟对象,并定义它们在测试中的行为。例如,我们可以模拟静态方法、构造函数或私有方法。可以用于模拟各个外部接口或者属性方法的数据。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
</dependency>

3、AssertJ

AssertJ提供了丰富的断言方法,使得断言更加简洁和易读。它支持链式断言和软断言,使得测试代码更加清晰。

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.2</version>
    <scope>test</scope>
</dependency>

二、常见模拟用法

1. 静态类

使用MockedStatic @Cleanup注解自动close。

@cleanup Mockedstatic<URLDecoder> urlDecoderMockedstatic =
                        Mockito.mockstatic(URLDecoder.class);
                urlDecoderMockedstatic.when(()->URLDecoder.decode(
                        Mockito.any(),Mockito.anystring())).
                        thenReturn(JsoNutil.toJsonstr(depositTradeResp));

2. 工具类

使用mockConstruction

Mockito.mockConstruction(AesUtil.class, (util, context) -> {
    Mockito.when(util.decryptMsg(Mockito.anyString())).thenReturn(true);
});

3. 私有方法

使用反射机制

Method checkCouponByQuery = createGoOrderService.getClass().getDeclaredMethod("checkCouponByQuery", List.class, List.class, List.class);
checkCouponByQuery.setAccessible(true);

try {
    checkCouponByQuery.invoke(createGoOrderService, addedXPlusOrderInfoList, usableCoupon, checkCouponResultList);
} catch (Exception e) {
    logger.info("异常信息:{}", e.getMessage());
}

4. 局部模拟

 ReflectUtil.setFieldValue(changeOrderService, "changeInfoMapper", changeInfoMapperOne);
BDDMockito.when(changeInfoMapperOne.getSubSegOrderList()).thenReturn(Arrays.asList("sdsd", "sds"));

三、单测类的实现

下面这个基类为Spring Boot应用程序的测试提供了一个基础框架,包括测试环境的配置、测试数据的加载、以及测试过程中所需的工具和资源的管理。这有助于确保测试的一致性、可重复性和可靠性。其中loadJsonParam 方法允许测试类从类路径下的文件中加载JSON数据,这在测试需要发送JSON请求的API时很有用。init 方法在每个测试方法之前初始化 MockMvc 对象,这是测试Spring MVC应用程序的关键步骤。after 方法可以用来执行测试后的清理工作。最后,getMockMvc 和 getParamJsonStr 方法提供了对 MockMvc 对象和JSON参数字符串的访问,以便在测试中使用。

package com.csair.ecs;

import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = GroupNeedServiceApplication.class)
@ActiveProfiles("test")
public class BaseTest {

    public static final String UTF_8 = "UTF-8";

    @Autowired
    private WebApplicationContext webAppConfiguration;

    private MockMvc mockMvc;

    private String paramJsonStr;

    public void loadJsonParam(String classPathJsonFileName) {
        StringBuilder sb = new StringBuilder(300);
        try (BufferedInputStream inputStream = new BufferedInputStream(
                Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathJsonFileName));
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, UTF_8))) {
            String temp;
            while ((temp = reader.readLine())!= null) {
                sb.append(temp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.paramJsonStr = sb.toString();
    }

    // 在每个测试方法执行之前,初始化MockMvc对象。
    @Before
    public void init() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webAppConfiguration).build();
    }

    // 在每个测试方法执行之后,可以执行清理工作。
    @After
    public void after() {
    }

    // 提供获取MockMvc对象的方法,以便在测试中使用。
    public MockMvc getMockMvc() {
        return mockMvc;
    }

    // 提供获取JSON参数字符串的方法,以便在测试中使用。
    public String getParamJsonStr() {
        return paramJsonStr;
    }
}

四、测试类实现

下面这个测试类通过继承 BaseTest 类,利用已经配置好的测试环境和工具。每个测试方法都设计来覆盖特定的功能点,确保服务在各种输入下都能正确执行。使用 Lombok 的 @Slf4j 注解简化了日志记录的配置,使得测试代码更加简洁。

@Slf4j
public class SystemParamsConfigServiceImplTest extends BaseTest {

    @Autowired
    private SystemParamsConfigService systemParamsConfigService;

    @Test
    public void testSelectParamsPageList() {
        // Test case 1
        SystemParamsConfigReq req1 = new SystemParamsConfigReq();
        req1.getPage().setPageNo(1);
        req1.getPage().setPageSize(5);
        ResponseBase<PageData<SystemParamsConfig>> responseBase1 = systemParamsConfigService.selectParamsPageList(req1);
        log.info("结果:{}", JSONUtil.parseObj(responseBase1));

        // Test case 2
        SystemParamsConfigReq req2 = new SystemParamsConfigReq();
        req2.getPage().setPageNo(1);
        req2.getPage().setPageSize(5);
        req2.setParamKey("dd");
        ResponseBase<PageData<SystemParamsConfig>> responseBase2 = systemParamsConfigService.selectParamsPageList(req2);
        log.info("结果:{}", JSONUtil.parseObj(responseBase2));

        // Test case 3
        SystemParamsConfigReq req3 = new SystemParamsConfigReq();
        req3.getPage().setPageNo(1);
        req3.getPage().setPageSize(5);
        req3.setRemark("d");
        ResponseBase<PageData<SystemParamsConfig>> responseBase3 = systemParamsConfigService.selectParamsPageList(req3);
        log.info("结果:{}", JSONUtil.parseObj(responseBase3));
    }

    @Test
    public void testGetByParamKey() {
        ResponseBase<SystemParamsConfig> responseBase = systemParamsConfigService.getByParamKey("aa");
        log.info("结果:{}", JSONUtil.parseObj(responseBase));
    }

    @Test
    public void testInsertParamConfig() {
        SystemParamsConfig paramsConfig = new SystemParamsConfig();
        paramsConfig.setParamKey(RandomUtil.randomNumbers(6));
        paramsConfig.setParamValue("测试一下");
        paramsConfig.setOperator("wangjiansheng9");
        paramsConfig.setRemark("备注一下");

        // Test case 1
        ResponseBase<Integer> responseBase1 = systemParamsConfigService.insertParamConfig(paramsConfig);
        log.info("结果:{}", JSONUtil.parseObj(responseBase1));
        setParamKey(paramsConfig.getParamKey());

        // Test case 2
        paramsConfig.setParamKey("ferferfrefrefrefer");
        ResponseBase<Integer> responseBase2 = systemParamsConfigService.insertParamConfig(paramsConfig);
        log.info("结果:{}", JSONUtil.parseObj(responseBase2));
    }
}

五、IDEA查看覆盖率

在IntelliJ IDEA中,鼠标右键选中某个单元测试类或包,选择 更多运行/调试 - 使用覆盖率 - 使用覆盖率运行。

覆盖率

等待单元测试运行结束,会在IDEA右侧弹出覆盖率面板。在代码中查看具体覆盖情况。










http://www.kler.cn/a/576373.html

相关文章:

  • lamp平台的应用
  • Linux13-TCP\HTTP
  • html css网页制作成品——糖果屋网页设计(4页)附源码
  • CODEGEN:一种基于多轮对话的大型语言模型编程合成方法
  • docker配置固定ip解决nginx代理容器名称dns缓存不更新问题
  • 【基础3】快速排序
  • TDengine SQL手册—删除数据
  • 搭建BOA服务器
  • 【MySQL_03】数据库基本--核心概念
  • Springboot 循环依赖
  • 深入解析京东商品详情 API 接口 item_get
  • Linux(Centos 7.6)命令详解:vim
  • 运维Zabbix面试题及参考答案
  • HCIA-路由重分布
  • Python接口自动化之断言封装!
  • LLM论文笔记 19: On Limitations of the Transformer Architecture
  • 鸿蒙HarmonyOS评论功能小demo
  • 考研题库与考研真题分别应该如何使用?
  • 搭建一套东郊到家上门按摩app需要多少钱?
  • 恶劣天候三维目标检测论文列表整理