UT主要使用powermock进行测试,powermock是easymock的改进版,相对于easymock:
a.更简单、直观,省去了easymock的一些步骤,学习成本低
b.支持静态函数单元测试
c.支持的注解比easymock更强大
下面通过例子,从三方面介绍powermock的单元测试方法,选择这三方面,主要是单元测试的写法略有区别:
a.被单元测试函数中调用了有返回值的函数
b.被单元测试的函数中调用了无返回值的函数
c.被单元测试的函数中需要调用静态函数
import java.util.HashMap;
import java.util.Map;
public class EmployeeController {
private EmployeeService employeeService;
public EmployeeController() {
this.employeeService = new EmployeeService();
}
public Map
Map
int actualEmployeeCount = employeeService.getEmployeeCount("A");
result.put("actualEmployeeCount", actualEmployeeCount);
return result;
}
public void saveEmployee() throws Exception {
Employee employee = new Employee();
employeeService.saveEmployee(employee);
}
public Map
Map
boolean result = CommonUtils.isWorking(name);
returned.put(name, result);
return returned;
}
}
public class EmployeeService {
private static String COMPANY_A = "A";
private static int COMPANY_A_EMPLOYEE_COUNT = 100;
public int getEmployeeCount(String companyName) {
if (COMPANY_A.equals(companyName)) {
return COMPANY_A_EMPLOYEE_COUNT;
} else {
return 0;
}
}
public void saveEmployee(Employee employee) {
throw new UnsupportedOperationException();
}
}
public class Employee {
}
import java.util.ArrayList;
import java.util.List;
public class CommonUtils {
public static boolean isWorking(String name) {
List
names.add("jack");
names.add("john");
names.add("marks");
return names.contains(name);
}
}
通过对EmployeeController中的各个函数进行单元测试,来标识三个方面的测试:
a.getProjectedEmployeeCount调用了employeeService.getEmployeeCount是有返回值的函数
b.saveEmployee调用了employeeService.saveEmployee是返回值为空的函数
c.isWorking调用了CommonUtils.isWorking是静态函数
对EmployeeController进行单元测试
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
//标识使用PowerMock测试,使用PowerMock测试必加
@RunWith(PowerMockRunner.class)
//标识会使用到CommonUtils中的静态函数,如果单元测试的函数中会使用某个类的静态函数必须提前将类Prepare
@PrepareForTest({ CommonUtils.class })
public class EmployeeControllerTest {
//被单元测试的类,相当于new一个对象
@InjectMocks
private EmployeeController employeeController;
//被单元测试的类中的函数需要调用的其他对象,使用mock虚拟化
@Mock
private EmployeeService employeeService;
//单元测试注解
@Test
public void getProjectedEmployeeCountTest() {
//虚拟化函数的返回值
Mockito.when(employeeService.getEmployeeCount(Mockito.anyString())).thenReturn(0);
Map
//断言返回的结果和预期一致
Assert.assertTrue(result.get("actualEmployeeCount") == 0);
}
//单元测试注解
@Test
public void saveEmployeeTest() {
//对于无返回值的函数,虚拟化什么也不做
Mockito.doNothing().when(employeeService).saveEmployee(Mockito.any(Employee.class));
Exception exception = null;
try {
employeeController.saveEmployee();
} catch (Exception exp) {
exception = exp;
}
//断言employeeController.saveEmployee没有异常产生
Assert.assertNull(exception);
}
//单元测试注解
@Test
public void isWorkingTest() {
//静态函数调用前准备
PowerMockito.mockStatic(CommonUtils.class);
//虚拟化静态函数的返回值
Mockito.when(CommonUtils.isWorking(Mockito.anyString())).thenReturn(false);
Map
//断言返回的结果和预期一致
Assert.assertFalse(returned.get("abc"));
}
}