service test with PowerMockito
@RunWith(PowerMockRunner.class)
@PrepareForTest({ProductServiceImpl.class, ProductGenerator.class, Product.class})
public class ProductServiceImplTest {
@Mock
private ProductRepo productRepo;
@Mock
private EventBus eventBus;
@Rule
private ExpectedException exception = ExpectedException.none();
private ProductServiceImpl productService;
@Before
public void init(){
productService = spy(new ProductServiceImpl(productRepo, eventBus));
//Whitebox.setInternalState(productService, "productRepo", productRepo); //当为private时
}
}
- @PrepareForTest: 包含静态方法的类、待测试的类等
- 待测试类要spy,而不是用mock。 另外,@InjectMocks不支持mock自身方法。当内部字段为private时,采用WhiteBox来设置内部状态
- 异常验证可以用@Test(expected=Xxx.class), 但要深入时,用@Rule ExpectedException。
when(productRepo.save(product)).thenReturn(product);
doReturn(new Product()).when(productService).findByName("p1");
doReturn(new Product()).when(productService, "findByNo", "n1");
doNothing().when(productService, "checkCategoryId", 0L);
doThrow(new RuntimeException("category.invalid")).when(productService, "checkCategoryId", 0L);
- suppress static constructor:
@SuppressStaticInitializationFor("top.zhacker.testdriven.product.model.Product")
- suppress instance constructor:
suppress(constructor(Product.class));
suppress(method(Product.class,"check", Product.class));
mockStatic(ProductGenerator.class); when(ProductGenerator.getNextId()).thenReturn("no");
mockStatic(Product.class); doNothing().when(Product.class, "check", any());
mockStatic(Product.class); doThrow(new RuntimeException("check.fail")).when(Product.class, "check", any());
whenNew(Product.class).withArguments("invalid").thenReturn(mock(Product.class));
when(productRepo.findByName(any())).then(invocationOnMock->{
String name = invocationOnMock.getArgument(0);
if(name.startsWith("pa")) return new Product("pa");
if(name.startsWith("pb")) return new Product("pb");
return null;
});
exception.expect(RuntimeException.class);
exception.expectMessage("check.fail");
verify(productRepo).save((Product)argThat(p->{ //overload
Product toSave = (Product)p; //overload
assertEquals("pa", toSave.getName());
assertNotNull(toSave.getCreatedAt());
assertNotNull(toSave.getNo());
assertNotNull(toSave.getUrl());
return true;
}));
verifyPrivate(productService).invoke("updateProduct", product);
verifyStatic(times(1)); Product.check(product); // invoke static verify, important