一、单元测试基本了解
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);
- 使用 Whitebox 将 airlineService 注入 priceService。
- 使用 when 指定 airlineService 的方法返回值。