单元测试初窥门径

一、单元测试基本了解

1. Mock概念

据百度百科:mock测试就是在测试过程中,对于某些不容易构造或者容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

2. powermock框架

单元测试(Unit Testing)是一种软件测试方法,是在软件开发过程中对软件模块进行校验的测试工作。

powermock 是Java 单元测试的一个框架,主要用于帮助开发者进行单元测试时模拟静态、私有、final等方法。

powermock 的主要功能有:

  • 模拟静态方法、构造函数、私有方法等的行为。
  • 跳过静态初始化器。
  • 验证私有方法、静态方法等的调用次数、参数等。
  • 替换静态方法、构造函数的实现逻辑等。

3. 常用注解

@PrepareForTest :

示例:

java 复制代码
@PrepareForTest({FlightMarketUtil.class})

官方解释是当我们虚拟构造final、static、等方法时加以注解。

这里我们mock调用的方法包(FlightMarketUtil)里面的方法都是静态,必然需要加入此注解。一般我们自己的方法包都要加入此注解。

@SuppressStaticInitializationFor : 忽略静态类不必要的初始化

示例:

java 复制代码
@SuppressStaticInitializationFor({"com.umetrip.data.UmeFlightTopology.base.scheduledload.FlightMarketUtil"})

官方解释是用此注解的方式来阻止静态代码块中代码的执行。

这个里面全是静态代码,也就是说我们调用这个包的方法去执行的话在测试类中不会真正执行。也不用担心不会返回结果,有指定方法返回结果的。

@mock:

由Mockito框架根据接口的实现帮我们mock一个虚假对象,该对象的方法不会真正去执行。对函数的调用均执行mock(即虚假函数),不执行真正部分。

@InjectMocks

由Mockito框架根据接口的实现帮我们创建一个实例对象(注意是实例对象,所以调用该类的方法都会被执行 )。简单的说是这个Mock可以调用真实代码的方法。

二、Mock方法架构

待测试代码

java 复制代码
public class UmeB2SService {

    public UmePsrSubscribeEnum sendConsentinfo(B2sConsentinfo b2sConsentinfo);
 }
\ .........
@Autowired
private UmeB2SService umeB2SService;
UmePsrSubscribeEnum umePsrSubscribeEnum = umeB2SService.sendConsentinfo(b2sConsentinfo);

也就是说,我们要调用 umeB2SService.sendConsentinfo方法,覆盖这段代码。

1、新建方法继承 extends PowerMockTestCase

scala 复制代码
public class B2SProxyTest extends PowerMockTestCase {

}

2、测试执行加注解@Test

java 复制代码
public class B2SProxyTest extends PowerMockTestCase {
    @Test
    public void Test(){
    
    }
}

3、调用方法测试

java 复制代码
public class UmeB2SServiceTest  extends PowerMockTestCase {
    @InjectMocks
    private UmeB2SService umeB2SService;
    
    @Test
    public void Test() {
        
        B2sConsentinfo b2sConsentinfo = generateB2sConsentinfo("NI", "*******", "崔****", "Dave");
        UmePsrSubscribeEnum umePsrSubscribeEnum = umeB2SService.sendConsentinfo(b2sConsentinfo);

    }

一般其他的方法直接调用就可以,但是这个是UmeB2SService,一个@Service注解的内容,需要@InjectMocks注解,

三、常见测试方法

1、常用非静态方法

待Mock代码块

java 复制代码
SendResult res = messageProducer.send(normalMessage);

这是原本的业务代码,使用 messageProducer 的 send 方法发送消息。

(1)测试类mock 对应类

java 复制代码
@Mock
MessageProducer messageProducer;

@Mock
SendResult sendResult;

使用 @Mock 注解模拟 MessageProducer 和 SendResult 两个类。

(2)单测代码

java 复制代码
PowerMockito.when(messageProducer.send(Mockito.any())).thenReturn(sendResult);

使用 PowerMockito 的 when 方法,指定 messageProducer 的 send 方法在被调用时返回 sendResult。

2、静态方法

待Mock代码块

java 复制代码
private static MessageProducer messageProducer;
messageProducer = MessageProducerBuilder.createBuilder().setProducerConfig(props).build();

原本代码使用 MessageProducerBuilder 的静态方法创建 MessageProducer 实例。

(1)加注解(后续需要Mock静态方法时必需)

java 复制代码
@PrepareForTest({MessageProducerBuilder.class})

加入 @PrepareForTest 注解,表示会模拟 MessageProducerBuilder 类的静态方法。

(2)测试类mock 对应类

less 复制代码
@Mock
MessageProducer messageProducer;

@Mock
MessageProducerBuilder messageProducerBuilder;

使用 @Mock 注解模拟 MessageProducerBuilder 和 MessageProducer 类。

(3)Mock类

java 复制代码
PowerMockito.mockStatic(MessageProducerBuilder.class);

使用 PowerMockito.mockStatic() 方法模拟 MessageProducerBuilder 类。

(4)单测代码

java 复制代码
PowerMockito.when(MessageProducerBuilder.createBuilder()).thenReturn(messageProducerBuilder);
PowerMockito.when(MessageProducerBuilder.createBuilder().setProducerConfig(Mockito.any())).thenReturn(messageProducerBuilder);
PowerMockito.when(MessageProducerBuilder.createBuilder().setProducerConfig(Mockito.any()).build()).thenReturn(messageProducer);

使用 when 方法分别指定 MessageProducerBuilder 的静态方法在被调用时的返回值。注意这里的多重调用一定要每次调用都mock,不然会报空指针。

3、Service接口方法

(1)测试类中mock

java 复制代码
@Mock
private AirlineService airlineService;

使用 @Mock 注解模拟 AirlineService 接口。

(2)mock代码块

java 复制代码
Whitebox.setInternalState(priceService, "airlineService", airlineService);
PowerMockito.when(airlineService.getAirlineRouteList(anyString())).thenReturn(airlineRoutePoList);
  1. 使用 Whitebox 将 airlineService 注入 priceService。
  2. 使用 when 指定 airlineService 的方法返回值。
相关推荐
老神在在00119 小时前
测试方法与使用场景
单元测试·测试
kyriewen111 天前
WebAssembly:前端界的“外挂”,让C++代码在浏览器里跑起来
开发语言·前端·javascript·c++·单元测试·ecmascript
测试员周周2 天前
【AI测试功能3】AI功能测试的三层架构:单元测试 → 集成测试 → E2E测试——AI系统测试金字塔实战指南
开发语言·人工智能·python·功能测试·架构·单元测试·集成测试
汽车仪器仪表相关领域2 天前
Kvaser Memorator Professional 5xHS CB:五通道CAN FD裸板记录仪,赋能多总线系统集成测试的旗舰级核心装备
大数据·网络·人工智能·单元测试·汽车·集成测试
测试员周周3 天前
【AI测试功能2】AI功能测试的“不可确定性“难题与应对思路:从精确断言到统计判定的完整方案
大数据·人工智能·python·功能测试·测试工具·单元测试·测试用例
中冕—霍格沃兹软件开发测试4 天前
区块链交易最终一致性测试的核心挑战与实践框架
微服务·架构·单元测试·区块链·集成测试·旅游
测试员周周4 天前
【AI测试系统】第5篇:AI 编码工具抛硬币?我们用 LangGraph 做了个“确定性+AI”的测试系统(附自愈架构)
人工智能·python·功能测试·测试工具·架构·langchain·单元测试
kyriewen5 天前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
小短腿的代码世界6 天前
Qt券商接口封装深度解析:统一API设计与多源适配
开发语言·qt·单元测试