首先引入依赖:
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
Mock普通公共的方法
User
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
private Long id;
private String name;
private Integer age;
}
UserDao:
public class UserDAO {
// 这里模拟连不上数据库的情况
public User getUserById(){
throw new UnsupportedOperationException();
}
}
UserService:
public class UserService {
private UserDAO userDAO = new UserDAO();
public User getById(){
return userDAO.getUserById();
}
}
测试类:
// 告诉JUnit使用PowerMockRunner进行测试
@RunWith(PowerMockRunner.class)
public class UserServiceTest extends TestCase {
@Mock
private UserDAO userDAO;
@InjectMocks
private UserService userService;
@Test
public void testGetById() {
Long id = 1L;
Integer age = 11;
String name = "花花";
Mockito.when(userDAO.getUserById()).thenReturn(User.builder().id(id).age(age).name(name).build());
User user = userService.getById();
Assert.assertEquals(id,user.getId());
}
}
Mock静态方法
静态方法FileUtil
public class FileUtil {
public static Boolean fileExists(String path){
return true;
}
}
FileService:
public class FileService {
public Boolean fileExists(String path){
return FileUtil.fileExists(path);
}
}
测试类:
@RunWith(PowerMockRunner.class)
@PrepareForTest({FileUtil.class})// 因为要mock这个类的静态方法,所以要准备一下
public class FileServiceTest extends TestCase {
@InjectMocks
private FileService fileService;
@Before
public void init(){
PowerMockito.mockStatic(FileUtil.class);// 先声明一下要模拟静态方法
}
public void testFileExists() {
PowerMockito.when(FileUtil.fileExists(Mockito.anyString()))
.thenReturn(false);
Boolean fileExists = fileService.fileExists("C:/user/readme.txt");
Assert.assertFalse(fileExists);
PowerMockito.when(FileUtil.fileExists(Mockito.anyString()))
.thenReturn(true);
Boolean fileExists1 = fileService.fileExists("C:/user/readme.txt");
Assert.assertTrue(fileExists1);
}
}
Mock私有方法
StringUtils:
public class StringUtils {
public String getString(String source, String subString){
if (exsitSubString(source, subString)){
return source;
} else {
return subString;
}
}
private boolean exsitSubString(String source, String subString){
return source.contains(subString);
}
}
测试类:
@RunWith(PowerMockRunner.class)
@PrepareForTest({StringUtils.class})
public class StringUtilsTest extends TestCase {
@InjectMocks
private StringUtils stringUtils;
// mock 私有方法
@Test
public void testGetString() throws Exception {
String source = "wangqinjie";
String subString = "qin";
StringUtils spy = PowerMockito.spy(stringUtils);// 监视某一个对象
// mock监视对象调用exsitSubString的方法是返回true
PowerMockito.when(spy, "exsitSubString", Mockito.anyString(),Mockito.anyString())
.thenReturn(true);
String string = spy.getString(source, subString);
Assert.assertEquals(source, string);
}
}
测试私有方法
有的时候我们为了代码很好的覆盖,我们需要覆盖有些类的私有的方法,那我们可以直接测试类中的私有方法。
注意:是测试私有方法,不是mock
public class DateUtils {
private Boolean isAfter30Days(Date startDate, Date endDate){
return true;
}
}
测试类:
public class DateUtilsTest extends TestCase {
// 方式一
@Test
public void testPrivate1() throws InvocationTargetException, IllegalAccessException {
// 创建一个对象
DateUtils dateUtils = new DateUtils();
// 获取这个类的某一个私有的方法。
Method method = PowerMockito.method(DateUtils.class, "isAfter30Days", Date.class, Date.class);
// 使用对象并传入参数,调用这个私有方法
Boolean isAfter = (Boolean) method.invoke(dateUtils, new Date(), new Date());
Assert.assertTrue(isAfter);
}
// 方式二
@Test
public void testPrivate2() throws Exception {
// 创建一个对象
DateUtils dateUtils = new DateUtils();
// 使用Whitebox写盒子直接调用这个对象的私有方法
Boolean isAfter = Whitebox.invokeMethod(dateUtils, "isAfter30Days", new Date(), new Date());
Assert.assertTrue(isAfter);
}
}
Mock局部变量
ToolItem
public class ToolItem {
public void run(){
System.out.println("run");
}
}
Tool
public class Tool {
public void run() {
ToolItem toolItem = new ToolItem();
toolItem.run();
}
}
ToolService
public class ToolService {
public void useTool(Tool tool){
tool.run();
}
}
测试类:
@RunWith(PowerMockRunner.class)
public class ToolServiceTest extends TestCase {
@InjectMocks
private ToolService toolService;
@Mock
private Tool tool;
public void testUseTool() throws Exception {
ToolItem toolItem = new ToolItem();
PowerMockito.whenNew(ToolItem.class).withNoArguments().thenReturn(toolItem);
toolService.useTool(tool);
// 证实tool的run方法被调用了,一般是用于证实void方法的
Mockito.verify(tool).run();
}
}
Mock final方法(类)
Room
final public class Room {
public String beSited(){
return "be sit";
}
}
RoomService
public class RoomService {
private Room room;
RoomService(Room room){
this.room = room;
}
public String beSit(){
return room.beSited();
}
}
测试类:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Room.class})
public class RoomServiceTest extends TestCase {
@Test
public void testBeSit() {
String sit = "be Sit";
Room mock = PowerMockito.mock(Room.class);
PowerMockito.when(mock.beSited()).thenReturn(sit);
RoomService roomService = new RoomService(mock);
String s = roomService.beSit();
Assert.assertEquals(sit, s);
}
}
另外一种方式:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Room.class})
public class RoomServiceTest extends TestCase {
@Mock
Room room;
@Test
public void testBeSit() {
String sit = "be Sit";
PowerMockito.when(room.beSited()).thenReturn(sit);
RoomService roomService = new RoomService(room);
String s = roomService.beSit();
Assert.assertEquals(sit, s);
}
}