覆盖catch,模拟new对象方法及私有方法处理
测试案例的Jmockit版本
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.38</version>
<scope>test</scope>
</dependency>
覆盖try catch中的异常处理逻辑
/**
* 业务代码中进行了异常处理
*/
@Override
public void catchExceptionService() {
try {
List<String> queryResultList = myMapper.queryAllList();
} catch (Exception e) {
log.error("查询数据集合时发生异常:{}", e);
}
}
测试案例模拟抛出异常,覆盖catch中的代码
/**
* 测试案例
*/
@Test
public void catchExceptionService_test() {
new Expectations() {
{
// 让该方法被调用时抛出异常
myMapper.queryAllList();
result = new RuntimeException();
}
};
myServicempl.catchExceptionService();
}
使用new MockUp模拟被测试代码中的私有方法
/**
* @author: xinruoxiangyang9010
* 业务代码:getOrderId()方法中调用了本类中的私有方法
*/
@Service
public class OrderServiceImpl implements OrderService {
@Override
public String getOrderId() {
List<String> orderIds = new ArrayList<>();
orderIds.add("01");
String productName = getProductName(orderIds);
// 以下可能会用productName做一些其他的业务逻辑
// .... ....
return "OrderXX";
}
private String getProductName(List<String> orderIdList) {
// 以下两行用于测试在mock时是否会调用真实代码逻辑
orderIdList.add("readId1");
orderIdList.add("readId2");
// 返回结果
return "Product01";
}
}
对于单测案例来说,我们应该只关注 getOrderId()代码体中的内容,而避免受getProductName()方法的结果而影响测试案例结果,所以将getProductName()方法mock掉
/**
* @author: xinruoxiangyang9010
* 测试案例:被测试的方法:orderService.getOrderId()
*/
@RunWith(JMockit.class)
public class OrderServiceImplTest {
@Tested
private OrderServiceImpl orderService;
@Test
public void getOrderId() {
new MockUp<OrderServiceImpl>() {
@Mock
private String getProductName(List<String> orderIdList){
return "mock01";
}
};
String orderId = orderService.getOrderId();
Assert.assertEquals("OrderXX", orderId);
}
}
可以通过断点模式看到,当方法getProductName()被调用时,直接按照我们Mock的结果进行返回,并没有进入到真实的方法中
使用 @Mocked对new的对象方法进行Mock
/**
* 业务代码1
* OrderCheck对象是new出来的,而不是注入的
* @return
*/
@Override
public String getOrderName() {
String orderName = "A000001";
OrderCheck orderCheck = new OrderCheck();
orderCheck.checkOrderName(orderName);
return orderName;
}
/**
* @author: xinruoxiangyang9010
* 业务代码2
* 以下的逻辑比较简单,但是如果遇到比较复杂的逻辑就不好调用真实方法了
*/
public class OrderCheck {
public void checkOrderName(String orderName) {
if (StringUtils.isEmpty(orderName) || !orderName.startsWith("B")) {
throw new RuntimeException("订单名称校验异常");
}
}
}
与上面的案例类似, 当不想测试结果受checkOrderName(String orderName)方法影响时,将他Mock掉
/**
* @author: xinruoxiangyang9010
* 测试案例
*/
@RunWith(JMockit.class)
public class OrderServiceImplTest {
@Mocked
private OrderCheck orderCheck;
@Tested
private OrderServiceImpl orderService;
@Test
public void getOrderName_test(){
new Expectations() {
{
orderCheck.checkOrderName(anyString);
result = null;
}
};
String orderName = orderService.getOrderName();
Assert.assertEquals("A000001", orderName);
}
}