用powermock编写单元测试

1、pom文件引入jar包

XML 复制代码
<!-- 单元测试 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.github.jsonzou</groupId>
    <artifactId>jmockdata</artifactId>
    <version>4.1.2</version>
    <scope>test</scope>
</dependency>
<!-- 单元测试 end -->

2、创建单元测试用例目录

保持与main级别一致,并且具体的测试用例存放目录也跟源代码的目录级别保持一致

3、单元测试类的基本框架

java 复制代码
@RunWith(PowerMockRunner.class)
@PrepareForTest({CommonUtils.class}) // 工具类
public class OrderServiceTest {

    @InjectMocks
    private OrderService orderService;

    @Mock
    private OrderMapper orderMapper;
	
	@Mock
    private OrderHelper orderHelper;
	
	@Before
    public void setUp() throws Exception {
		PowerMockito.mockStatic(CommonUtils.class);
    }
	
	// 被测试的方法 orderService.pageOrderRecord有返回值
	@Test
    public void testPageOrderRecord() {
	
		// Gievn
        OrderRecordDTO orderRecordDTO = new OrderRecordDTO();
        orderRecordDTO.setId("111");
        orderRecordDTO.setPageIndex(1);
        orderRecordDTO.setPageSize(10);

		// When
        OrderRecordEntity orderRecord = JMockData.mock(OrderRecordEntity.class);
        List<OrderRecordEntity> mock = Lists.newArrayList();
        mock.add(orderRecord);
        PowerMockito.when(orderMapper.selectEntityListPage(any())).thenReturn(mock); // mock的方法有返回值
        PowerMockito.doNothing().when(orderHelper).fillData(any()); // mock的方法没有返回值
        PowerMockito.when(CommonUtils.doPageQuery(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(new PageRows<>()); // mock工具类方法

		// Run the test
        PageRows<OrderRecordDTO> rt = orderService.pageOrderRecord(OrderRecordDTO);
		
		// Verify the results
        Assert.assertNotNull(rt);
    }

}

4、常见单元测试问题

4.1、静态方法如何mock

参见基本框架里的CommonUtils.doPageQuery()的mock。

如果被测试类的方法中调用到了静态方法CommonUtils.doPageQuery(),在写测试类的时候就需要主要注意:

@PrepareForTest({CommonUtils.class})、

PowerMockito.mockStatic(CommonUtils.class);

4.2、返回类型为void的方法如何mock

参见基本框架里的orderHelper.fillData()方法的mock。

4.3、被@Value注解的值如何mock

ReflectionTestUtils.setField(对象,"成员变量","变量mock值");

被测试类:

java 复制代码
@Component
public class OrderExternalFacade {
    @Autowired
    private OrderAbility OrderAbility;

    @Autowired
    private OrderExternalConvertor OrderExternalConvertor;

    @Value("${switch.new.system:false}")
    protected boolean switchNewSystem;

	public PageRows<OrderVO> listOrder(OrderQueryVO OrderQueryVO) {
        if (switchNewSystem) {
            return OrderExternalConvertor.pageDto2PageVo(
                    OrderAbility.listOrder(OrderExternalConvertor.queryVo2ModelQuery(OrderQueryVO)));
        }
        return OrderExternalConvertor.pageDto2PageVo(
                    OrderAbility.listOrderFromEpm(OrderExternalConvertor.queryVo2QueryDto(OrderQueryVO)));
    }
}

单元测试类:

java 复制代码
@RunWith(PowerMockRunner.class)
public class OrderExternalFacadeTest {
    @InjectMocks
    private OrderExternalFacade OrderExternalFacade;

    @Mock
    private OrderAbility OrderAbility;

    @Mock
    private OrderExternalConvertor OrderExternalConvertor;

    @Test
    public void listOrder() {
        ReflectionTestUtils.setField(OrderExternalFacade, "switchNewSystem", true);
        when(OrderExternalConvertor.queryVo2ModelQuery(any())).thenReturn(new OrderModelQueryDTO());
        when(OrderAbility.listOrder(any())).thenReturn(new PageRows<>());
        when(OrderExternalConvertor.pageDto2PageVo(any())).thenReturn(new PageRows<>());
        PageRows<OrderVO> rt = OrderExternalFacade.listOrder(new OrderQueryVO());

        Assert.assertNotNull(rt);
    }
}

4.4、返回类型为void的方法如何断言

验证调用次数:verify(OrderService, times(1)).insertOrder(orderBO);

被测试类:

java 复制代码
public class OrderService{

	@Autowired
	private OrderDao OrderDao;
	

	/**
	 * 添加订单
	 * @param OrderBO
	 * @throws Exception
	 */
	@Override
	public void insertOrder(OrderBO OrderBO) throws Exception{
		OrderDao.insertOrder(OrderBO);
	}
}

单元测试类:

java 复制代码
@RunWith(PowerMockRunner.class)
public class OrderServiceTest {

    @InjectMocks
    private OrderService OrderService;

    @Mock
    private OrderDao OrderDao;

    @Before
    public void setUp() throws Exception {}


    @Test
    public void testinsertOrder() throws Exception {

        OrderBO orderBO = new OrderBO();
        orderBO.setHandleType("order");
        orderBO.setBoId("1234568");
        orderBO.setHandeleSuggest("submit");

        // 如何mock 返回类型为void的方法
        PowerMockito.doNothing().when(OrderDao).insertOrder(any());
      
        //when
        OrderService.insertOrder(orderBO);
        
        verify(OrderService, times(1)).insertOrder(orderBO);

    }

}

4.5、异常如何断言

被测试类:

java 复制代码
public void delete(List<String> ids, String requiredBillId) {
	RequiredBillEntity requiredBill = requiredBillMapper.selectEntity(requiredBillId);
	if (requiredBill == null){
		throw new BusinessException(RetCode.BUSINESSERROR_CODE, MessageConst.REQUIRED_BILL_NOT_FOUND);
	}

	if (!RequiredBillStatusEnum.DRAFT.getStatus().equals(requiredBill.getStatus())){
		throw new BusinessException(RetCode.BUSINESSERROR_CODE, MessageConst.REQUIRED_BILL_STATUS_NOT_DRAFT);
	}
	requiredBillDetailMapper.deleteEntities(new ParamsMap("id_IN", ids));
}

测试类:

java 复制代码
@Test
public void testDelete() {

	List<String> ids = Lists.newArrayList();
	ids.add("dddd");
	String requiredBillId = "ddd";

	when(requiredBillMapper.selectEntity(anyString())).thenReturn(null);

    // 断言业务异常
	try {
		requiredBillDetailService.delete(ids,requiredBillId);
		fail("Expected BusiException");
	} catch (BusiException e) {
		assertEquals(RetCode.BUSINESSERROR_CODE, e.getExCode());
		assertEquals(REQUIRED_BILL_NOT_FOUND, e.getMessage());
	}

}

简洁的一点的话:

java 复制代码
@Test
public void testDelete() {

	List<String> ids = Lists.newArrayList();
	ids.add("dddd");
	String requiredBillId = "ddd";

	when(requiredBillMapper.selectEntity(anyString())).thenReturn(null);

    // 断言业务异常
	Assert.assertThrows(BusinessException.class, () ->requiredBillDetailService.delete(requiredBillDetailDTO));

}
相关推荐
Warren985 小时前
Pytest Fixture 作用域详解:Function、Class、Module、Session 怎么选
面试·职场和发展·单元测试·pytest·pip·模块测试·jira
一晌小贪欢2 天前
Python 测试利器:使用 pytest 高效编写和管理单元测试
python·单元测试·pytest·python3·python测试
汽车仪器仪表相关领域2 天前
MTX-A 模拟废气温度(EGT)计 核心特性与车载实操指南
网络·人工智能·功能测试·单元测试·汽车·可用性测试
卓码软件测评2 天前
第三方软件课题验收测试【使用Docker容器部署LoadRunner负载生成器以实现弹性压测 】
测试工具·docker·容器·性能优化·单元测试·测试用例
Apifox.3 天前
Apifox 1 月更新|MCP 调试、测试套件、测试报告重构、网络信息查看、Hoppscotch 导入
前端·人工智能·测试工具·单元测试·团队开发
卓码软件测评3 天前
第三方移动应用测试机构:【移动应用性能测试:使用LoadRunner的Mobile Application - HTTP/HTML协议】
测试工具·ci/cd·性能优化·单元测试·测试用例
汽车仪器仪表相关领域3 天前
70A大电流+三档电压可调:Midtronics MSP-070系列电源充电器汽车ECU刷新与电池维护实战全解
人工智能·功能测试·单元测试·汽车·可用性测试
我送炭你添花3 天前
Pelco KBD300A 模拟器:18. 按依赖顺序 + 复杂度由低到高逐步推进pytest单元测试
python·单元测试·log4j·pytest
CodeCraft Studio3 天前
Parasoft是什么?Parasoft自动化测试工具与解决方案:实现规模化应用
自动化测试·测试工具·单元测试·静态测试·parasoft·嵌入式软件测试·软件安全合规
卓码软件测评3 天前
【第三方双重资质软件测试机构:测试RESTful API和SOAP Web Services:LoadRunner协议选择和脚本编写】
测试工具·ci/cd·性能优化·单元测试·测试用例·restful