单元测试初窥门径

一、单元测试基本了解

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 的方法返回值。
相关推荐
程序猿000001号1 天前
探索Python的pytest库:简化单元测试的艺术
python·单元测试·pytest
星蓝_starblue2 天前
单元测试(C++)——gmock通用测试模版(个人总结)
c++·单元测试·log4j
whynogome3 天前
单元测试使用记录
单元测试
字节程序员3 天前
使用JUnit进行集成测试
jmeter·junit·单元测试·集成测试·压力测试
love静思冥想4 天前
Java 单元测试中 JSON 相关的测试案例
java·单元测试·json
乐闻x5 天前
如何使用 TypeScript 和 Jest 编写高质量单元测试
javascript·typescript·单元测试·jest
Cachel wood5 天前
Vue.js前端框架教程4:Vue响应式变量和指令(Directives)
前端·vue.js·windows·python·单元测试·django·前端框架
@TangXin5 天前
单元测试-Unittest框架实践
单元测试
十年一梦实验室6 天前
【C++】sophus : test_macros.hpp 用于单元测试的宏和辅助函数 (四)
开发语言·c++·单元测试
编码浪子6 天前
Springboot3.x配置类(Configuration)和单元测试
单元测试