单元测试Mock中常见问题与解决方案

很久不写博客了,经常搜索前辈和晚辈写的问题解决方案,得到很多帮助,也受益匪浅,所以也时常感到愧疚。那么接下来一段时间,我也分享一些技术点,问题方案吧。闻道有先后,术业有专攻。也希望我们都能保持一颗谦卑的心向身边或网络上的人学习,因为每个人都有自己的闪光点......

本篇单元测试暂时局限于mock、powermock,引用的jar包,大家自行百度吧。很简单。Demo样例,网上也多,后续我也可以给大家一些代码样例。

一、常见问题与解决方案

1、when().thenReturn()中常见问题

1.1. mock模拟的请求参数是对象,传入对象的每个元素值都对,但是报错

SysInfo sysInfo = new SysInfo();

sysInfo.setAct("abc");

when(systemInfoService.querySysParamsCount(sysInfo)).thenReturn(1);

问题:功能代码运行时生成的对象和mock传入的对象,对象内每个元素的值都一样,但是返回异常。

解决方案:请求对象对应的类SysInfo没有重写equals和hashCode方法。

传入的对象是map,会有这种问题吗?

不会。

1.2. 请求参数除了可以用any(),anyString,还可以用什么替代?

解决方案:还可以用any(类名.class)

1.3. 模拟while、for循环的参数时,如何跳出循环?

解决方案:thenReturn后再增加一个thenReturn,意思就是返回值有多种情况。第二次遍历时,就会变成下一个返回值。

例如:

when(systemInfoService.querySysParams(any()).thenReturn(sysInfoList ).thenReturn(sysInfoList2 );

1.4. 静态变量的mock------MockedStatic,多个类使用时,出现already regestered的问题

例如声明了一个MockedStatic

复制代码
MockedStatic<DateUtil> dateUtilMockedStatic;

解决方案:

有可能是因为静态变量没关闭,那么就在调用的方法内执行到最后调用这个静态mock的close方法,或者在@After对应方法内,调用它的close方法。

还有一种更容易发生的错误,前面没加this

生成这个变量,关闭它,都要在前面加"this."

也就是

复制代码
MockedStatic<DateUtil> dateUtilMockedStatic;

@Before
public void setUp() {
    openMocks(this);
    this.dateUtilMockedStatic = mockStatic(DateUtil.class);
}

@After
public void destroy(){
    this.dateUtilMockedStatic.close();
}

why?应该是因为,我们声明的静态变量不加this,就是属于整个包或者整个项目,所以导致的重复注册问题。

二、注意事项:

1、我们是写单元测试的,不是写功能代码的,功能业务代码,一般是不能因为写单元测试去改动的!!!这一点非常重要。

2、单元测试代码也要尽可能优化,尽量不要为了简单,把对一个公共方法的单元测试,分几个好几个方法去mock测试,这样产生了大量冗余代码,也会增加编译运行时间,降低项目性能与开发效率。

三、单元测试中Idea工具调优与使用技巧

1、如果是gradle作为jar包版本工具,要配置gradle,让它编译和运行都在idea上直接执行,而不是在gradle工具上执行。

2、多个单元测试代码写完,可以选择test的根目录、主目录,执行单元测试。这样可以发现多个单元测试文件同时执行时的问题,及时改正,快速提高单元测试覆盖率。

四、单元测试代码样例

java 复制代码
package com.example.demo;

import org.assertj.core.util.DateUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;

import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.openMocks;

/**
 * @Author HenryLee
 * @Description TODO
 * @Date 2024/5/27 22:16
 * @Version 1.0
 */
public class MyControllerTest {

    @InjectMocks
    private MyController myController;

    MockedStatic<DateUtil> dateUtilMockedStatic;

    @Before
    public void setUp() {
        openMocks(this);
        this.dateUtilMockedStatic = mockStatic(DateUtil.class);
    }

    @After
    public void destroy(){
        this.dateUtilMockedStatic.close();
    }


    @Test
    public void testController() {
        when(myController.getMsg()).thenReturn(null);
    }

}
相关推荐
安冬的码畜日常1 分钟前
【JUnit实战3_17】第九章:容器内测试(下)——Arquillian 框架的用法简介
测试工具·junit·单元测试·junit5·arquillian·容器内测试·in-container
虫无涯17 小时前
解锁 Playwright 自动化测试:一篇教程入门WebUI自动化测试【入门级】
python·单元测试·测试
安冬的码畜日常1 天前
【JUnit实战3_09】第五章:软件测试的基本原则简介
功能测试·测试工具·junit·单元测试·junit5
安冬的码畜日常1 天前
【JUnit实战3_12】第七章:用 Stub 模拟进行粗粒度测试
测试工具·junit·单元测试·junit5·stub模拟·模拟技术·stub 桩
程序员二黑2 天前
状态迁移与场景法:搞定复杂业务流测试的利器
面试·单元测试·测试
卓码软件测评4 天前
软件可用性测试历史概念✅软件可用性测试的国际标准✅软件可用性测试方法
数据库·单元测试·可用性测试·软件需求
JuicyActiveGilbert4 天前
【Python进阶】第2篇:单元测试
开发语言·windows·python·单元测试
Pluto_CSND4 天前
Java实现gRPC双向流通信
java·开发语言·单元测试
安冬的码畜日常5 天前
【JUnit实战3_08】第四章:从 JUnit 4 迁移到 JUnit 5
junit·单元测试·junit5·junit4·junit版本迁移
workflower5 天前
基本作业-管理⾃⼰的源代码
开发语言·单元测试·软件工程·需求分析·个人开发