在使用powermock时,要测试的类里有@Autowired方式注入的dao类,同时我还要mock这个类里的私有方法,所以使用了powermock的@PrepareForTest注解,但是在加上@PrepareForTest注解后,原本mock的dao类,在test时,报了java.lang.NullPointerException,mock的dao没有注入成功,不明白是否是powermock的bug,最后只能通过另外一种方式来将dao注入到要测试的类里,如下:
/**
* @InjectMocks 声明这个对象中的属性会被自动注入进来, 也就是下面 mock 出来的 userService
* 注意这里说的 mock 出来的对象, 包括 @Mock 和 @Spy 声明的对象
*/
@InjectMocks
private ContractBillService contractBillService;
/**
* 使用 @Mock 生成的类, 所有方法都不是真实的方法, 而且返回值都是NULL.
* 与之对应的还有个 @Spy
* 使用 @Spy 生成的类, 所有方法都是真实方法, 返回值都是和真实方法一样的
*/
@Mock
private ConContractBillDao conContractBillDao;
@Mock
private ConContractBillDetailDao conContractBillDetailDao;
@Test
@PrepareForTest(ContractBillService.class)
public void testConNewSignBill_success() throws Exception {
String contractGuid = "1";
// 这里录制脚本
// 当我们对 @Mock 的类进行模拟方法时, 会像下面这样去做:
// when(userService.loadUserById(any(String.class))).thenReturn(Optional.of(mockUser));
// 当我们对 @Spy 的类进行模拟方法时, 会像下面这样去做:
// doReturn(Optional.of(mockUser)).when(userService).loadUserById(any(String.class));
when(conContractBillDao.deleteAny(any(ConContractBill.class))).thenReturn(1);
when(conContractBillDetailDao.deleteAny(any(ConContractBillDetail.class))).thenReturn(1);
// mock私有方法
ContractBillService spy = PowerMockito.spy(contractBillService);
ReflectionTestUtils.setField(spy, "conContractBillDao", conContractBillDao);
ReflectionTestUtils.setField(spy, "conContractBillDetailDao", conContractBillDetailDao);
doNothing().when(spy, "caleFirstPayBill", any(), any(), any());
doNothing().when(spy, "caleScheduleBill", any(), any(), any(), any());
doNothing().when(spy, "caleDepositBill", any(), any());
// 执行你的逻辑
Response<Void> response = spy.conNewSignBill(contractGuid);
// 断言
assertThat(response.getCode(), is(IResultCode.SUCCESS));
}
其中起主要作用的就是:
ReflectionTestUtils.setField(spy, "conContractBillDao", conContractBillDao);
ReflectionTestUtils.setField(spy, "conContractBillDetailDao", conContractBillDetailDao);