使用PowerMock进行Mock测试
安装
下载地址:https://github.com/jayway/powermock/wiki/Downloads。下载" Mockito and JUnit including dependencies"版本。当前版本为”powermock-mockito-junit-1.6.3.zip"。
IntelliJ IDEA的设置如下:
右击工程,选择“Open Module Settings”
按下“ALT + Insert”,选择“Jars or directories...", 插入jar包:
点击OK。
在”Module Settings”对话框中点击“Sources”标签,右击右边底部面板,选择“New Folder...", 命名为test。
在”Module Settings”对话框中选择test,标识为Test Sources,关闭”Module Settings”对话框。
Eclipse中只需要上述jar包放在工程下的lib目录即可。
Maven在pom.xml添加如下内容:
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.3</version> <scope>test</scope> </dependency>
快速入门
下面创建EmployeeController类用于给Employee类执行Create, Read, Update, and Delete (CRUD)。实际工作由EmployeeService完成。getProjectedEmployeeCount方法预计公司员工每年增加20%,并返回近似取整。
public class EmployeeController { private EmployeeService employeeService; public EmployeeController(EmployeeService employeeService) { this.employeeService = employeeService; } public int getProjectedEmployeeCount() { final int actualEmployeeCount = employeeService.getEmployeeCount(); return (int) Math.ceil(actualEmployeeCount * 1.2); } public void saveEmployee(Employee employee) { employeeService.saveEmployee(employee); } }
public class EmployeeService { public int getEmployeeCount() { throw new UnsupportedOperationException(); } public void saveEmployee(Employee employee) { throw new UnsupportedOperationException(); } }
由于getEmployeeCount等方法没有真正实现,我们需要mock:
public class Employee { }
import static org.junit.Assert.*; import org.junit.Test; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; public class EmployeeControllerTest { @Test public void shouldReturnProjectedCountOfEmployeesFromTheService() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); PowerMockito.when(mock.getEmployeeCount()).thenReturn(8); EmployeeController employeeController = new EmployeeController(mock); assertEquals(10, employeeController.getProjectedEmployeeCount()); } @Test public void shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); EmployeeController employeeController = new EmployeeController(mock); Employee employee = new Employee(); employeeController.saveEmployee(employee); Mockito.verify(mock).saveEmployee(employee); } }
注意如果上述代码出现莫名其妙的错误,建议先确认所有文件已经保存,再不行重启Eclipse。
上面的saveEmployee(Employee)没有返回值,我们只需要用verify确认有调用即可。如果注释掉employeeController.saveEmployee(employee);就会有如下报错:
Wanted but not invoked: employeeService.saveEmployee( Employee@51081592 ); -> at EmployeeControllerTest.shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee(EmployeeControllerTest.java:27) Actually, there were zero interactions with this mock. at EmployeeControllerTest.shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee(EmployeeControllerTest.java:27) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
另外有个非常用的MockSettings功能,用于设置mock名、实现额外接口(参见https://groups.google.com/forum/?fromgroups=#!topic/mockito/YM5EF0x90_4)、开启详细日志、注册listener用于mock时通知消息调用。比如:
EmployeeService mock = PowerMockito.mock(EmployeeService.class, Mockito.withSettings().name("EmployeeServiceMock").verboseLogging());
注意:Eclipse如果看不到lib,请选中工程目录,按F5刷新。lib中的每个jar,需要右键点击,选择"Build Path"->"Add to Build Path", 添加完毕的效果图如下:
模拟静态方法
修改类Employee:
public class Employee { public static int count() { throw new UnsupportedOperationException(); } }
修改EmployeeService类的方法:
public int getEmployeeCount() { return Employee.count(); }
新建EmployeeServiceTest类:
import static org.junit.Assert.*; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(Employee.class) public class EmployeeServiceTest { @Test public void shouldReturnTheCountOfEmployeesUsingTheDomainClass() { PowerMockito.mockStatic(Employee.class); PowerMockito.when(Employee.count()).thenReturn(900); EmployeeService employeeService = new EmployeeService(); assertEquals(900, employeeService.getEmployeeCount()); } }
@RunWith(PowerMockRunner.class)语句告诉JUnit用PowerMockRunner来执行测试。
@PrepareForTest(Employee.class)语句告诉PowerMock准备Employee类进行测试。适用于模拟final类或有final, private, static, native
方法的类。
注意这里使用的是mockStatic而不是上面的mock。
下面我们模拟下返回void的静态方法。在Employee添加加薪方法:
public static void giveIncrementOf(int percentage) { throw new UnsupportedOperationException(); }
EmployeeService添加相应方法:
public boolean giveIncrementToAllEmployeesOf(int percentage) { try{ Employee.giveIncrementOf(percentage); return true; } catch(Exception e) { return false; } }
修改EmployeeServiceTest类
import static org.junit.Assert.*; import org.junit.Test; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; public class EmployeeControllerTest { @Test public void shouldReturnProjectedCountOfEmployeesFromTheService() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); PowerMockito.when(mock.getEmployeeCount()).thenReturn(8); EmployeeController employeeController = new EmployeeController(mock); assertEquals(10, employeeController.getProjectedEmployeeCount()); } @Test public void shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); EmployeeController employeeController = new EmployeeController(mock); Employee employee = new Employee(); employeeController.saveEmployee(employee); Mockito.verify(mock).saveEmployee(employee); } }
PowerMockito.doNothing方法告诉PowerMock下一个方法调用时什么也不做。
PowerMockito.doThrow方法告诉PowerMock下一个方法调用时产生异常。
PowerMock使用自定义类加载器和字节码操作来模拟静态方法。对于实例中没有mock的方法,也有默认返回值,比如返回int类型的方法,默认返回0。
PowerMockito.doNothing和PowerMockito.doThrow的语法可用于实例方法。
先在Employee类添加方法save:
public void save() { throw new UnsupportedOperationException(); }
创建测试EmployeeTest 类:
import static org.junit.Assert.*; import org.junit.Test; import org.powermock.api.mockito.PowerMockito; public class EmployeeTest { @Test() public void shouldNotDoAnythingIfEmployeeWasSaved() { Employee employee = PowerMockito.mock(Employee.class); PowerMockito.doNothing().when(employee).save(); try { employee.save(); } catch(Exception e) { fail("Should not have thrown an exception"); } } @Test(expected = IllegalStateException.class) public void shouldThrowAnExceptionIfEmployeeWasNotSaved() { Employee employee = PowerMockito.mock(Employee.class); PowerMockito.doThrow(new IllegalStateException()).when(employee).save(); employee.save(); } }
注意这里doThrow和doNothing方法不会对下一行产生影响。
验证方法调用
验证断言方法是否调用。
修改EmployeeService类的saveEmployee方法。
public void saveEmployee(Employee employee) { if(employee.isNew()) { employee.create(); return; } employee.update(); }
修改Employee类,新增如下方法:
public boolean isNew() { throw new UnsupportedOperationException(); } public void update() { throw new UnsupportedOperationException(); } public void create() { throw new UnsupportedOperationException(); }
在EmployeeServiceTest类中新增shouldCreateNewEmployeeIfEmployeeIsNew方法, 并新增导入import org.mockito.Mockito;:
@Test public void shouldCreateNewEmployeeIfEmployeeIsNew() { Employee mock = PowerMockito.mock(Employee.class); PowerMockito.when(mock.isNew()).thenReturn(true); EmployeeService employeeService = new EmployeeService(); employeeService.saveEmployee(mock); Mockito.verify(mock).create(); Mockito.verify(mock, Mockito.never()).update(); }
Mockito.verify(mock).create()验证调用了create方法。 Mockito.verify(mock, Mockito.never()).update();验证没有调用update方法。
下面验证静态方法,在EmployeeServiceTest类添加shouldInvoke_giveIncrementOfMethodOnEmployeeWhileGivingIncrement方法:
@Test public void shouldInvoke_giveIncrementOfMethodOnEmployeeWhileGivingIncrement() { PowerMockito.mockStatic(Employee.class); PowerMockito.doNothing().when(Employee.class); Employee.giveIncrementOf(9); EmployeeService employeeService = new EmployeeService(); employeeService.giveIncrementToAllEmployeesOf(9); PowerMockito.verifyStatic(); Employee.giveIncrementOf(9); }
同样,静态验证也要分两步走。
其他验证模式可以验证调用次数:
Mockito.times(int n) : This verification mode asserts that the mocked method was invoked exactly 'n' times
Mockito.atLeastOnce() : This verification mode asserts that the mocked method was invoked at least once
Mockito.atLeast(int n) : This verification mode asserts that the mocked method was invoked at least 'n' times
Mockito.atMost(int n) : This verification mode asserts that the mocked method was invoked at most 'n' times
使用Mockito.inOrder还可以验证调用的顺序,注意要导入import org.mockito.InOrder;
@Test public void shouldInvokeIsNewBeforeInvokingCreate() { Employee mock = PowerMockito.mock(Employee.class); PowerMockito.when(mock.isNew()).thenReturn(true); EmployeeService employeeService = new EmployeeService(); employeeService.saveEmployee(mock); InOrder inOrder = Mockito.inOrder(mock); inOrder.verify(mock).isNew(); Mockito.verify(mock).create(); Mockito.verify(mock, Mockito.never()).update(); }
模拟final类或方法
新增EmployeeIdGenerator类:
public final class EmployeeIdGenerator { public final static int getNextId() { throw new UnsupportedOperationException(); } }
在Employee类新增方法:
public void setEmployeeId(int nextId) { throw new UnsupportedOperationException(); }
修改EmployeeService类的saveEmployee方法:
public void saveEmployee(Employee employee) { if(employee.isNew()) { employee.setEmployeeId(EmployeeIdGenerator.getNextId()); employee.create(); return; } employee.update(); }
修改EmployeeServiceTest类:
import static org.junit.Assert.*; import org.junit.Test; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; public class EmployeeControllerTest { @Test public void shouldReturnProjectedCountOfEmployeesFromTheService() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); PowerMockito.when(mock.getEmployeeCount()).thenReturn(8); EmployeeController employeeController = new EmployeeController(mock); assertEquals(10, employeeController.getProjectedEmployeeCount()); } @Test public void shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); EmployeeController employeeController = new EmployeeController(mock); Employee employee = new Employee(); employeeController.saveEmployee(employee); Mockito.verify(mock).saveEmployee(employee); } }
可见final和static的在类头部处理方法类似, 在测试方法中final和普通方法类似。
处理构造方法
现在创建新职员的时候要发送欢迎邮件。
新增类WelcomeEmail:
public class WelcomeEmail { public WelcomeEmail(final Employee employee, final String message) { throw new UnsupportedOperationException(); } public void send() { throw new UnsupportedOperationException(); } }
修改EmployeeService类的saveEmployee方法:
public void saveEmployee(Employee employee) { if(employee.isNew()) { employee.setEmployeeId(EmployeeIdGenerator.getNextId()); employee.create(); WelcomeEmail emailSender = new WelcomeEmail(employee, "Welcome to Mocking with PowerMock How-to!"); emailSender.send(); return; } employee.update(); }
import static org.junit.Assert.*; import org.junit.Test; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; public class EmployeeControllerTest { @Test public void shouldReturnProjectedCountOfEmployeesFromTheService() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); PowerMockito.when(mock.getEmployeeCount()).thenReturn(8); EmployeeController employeeController = new EmployeeController(mock); assertEquals(10, employeeController.getProjectedEmployeeCount()); } @Test public void shouldInvokeSaveEmployeeOnTheServiceWhileSavingTheEmployee() { EmployeeService mock = PowerMockito.mock(EmployeeService.class); EmployeeController employeeController = new EmployeeController(mock); Employee employee = new Employee(); employeeController.saveEmployee(employee); Mockito.verify(mock).saveEmployee(employee); } }
注意PowerMockito.verifyNew的第2个参数支持前面提到的验证模式。PowerMockito.whenNew().withArguments(...).thenReturn()是对构造方法的mock模式,PowerMockito.verifyNew().withArguments()是验证模式。
参数匹配
PowerMock使用equals方法验证参数。matcher可更加灵活的处理参数。
为EmployeeController类添加如下方法:
public Employee findEmployeeByEmail(String email) { return employeeService.findEmployeeByEmail(email); } public boolean isEmployeeEmailAlreadyTaken(String email) { Employee employee = new Employee(); return employeeService.employeeExists(employee); }
为EmployeeService类添加如下方法:
public Employee findEmployeeByEmail(String email) { throw new UnsupportedOperationException(); } public boolean employeeExists(Employee employee) { throw new UnsupportedOperationException(); }
为EmployeeControllerTest类新增测试
@Test public void shouldFindEmployeeByEmail() { final EmployeeService mock = PowerMockito.mock(EmployeeService.class); final Employee employee = new Employee(); PowerMockito.when(mock.findEmployeeByEmail(Mockito.startsWith("deep"))).thenReturn(employee); final EmployeeController employeeController = new EmployeeController(mock); assertSame(employee, employeeController.findEmployeeByEmail("deep@gitshah.com")); assertSame(employee, employeeController.findEmployeeByEmail("deep@packtpub.com")); assertNull(employeeController.findEmployeeByEmail("noreply@packtpub.com")); } @Test public void shouldReturnNullIfNoEmployeeFoundByEmail() { final EmployeeService mock = PowerMockito.mock(EmployeeService.class); PowerMockito.when(mock.findEmployeeByEmail(Mockito.anyString())).thenReturn(null); final EmployeeController employeeController = new EmployeeController(mock); assertNull(employeeController.findEmployeeByEmail("deep@gitshah.com")); assertNull(employeeController.findEmployeeByEmail("deep@packtpub.com")); assertNull(employeeController.findEmployeeByEmail("noreply@packtpub.com")); }
后面还有个基于argThat例子,因为没有搞到源码,意思暂时没有揣度出来。先不涉及。
另外其他类似的内置匹配器如下:Mockito.eq、Mockito.matches、Mockito.any(anyBoolean , anyByte , anyShort , anyChar , anyInt ,anyLong , anyFloat , anyDouble , anyList , anyCollection , anyMap , anySet等等)、Mockito.isNull、Mockito.isNotNull、Mockito.endsWith、Mockito.isA。
回答(Answer)
在某些边缘的情况下不可能通过简单地通过PowerMockito.when().thenReturn()模拟,这时可以使用Answer接口。
在EmployeeControllerTest类中增加如下方法:
@Test public void shouldFindEmployeeByEmailUsingTheAnswerInterface() { final EmployeeService mock = PowerMockito.mock(EmployeeService.class); final Employee employee = new Employee(); PowerMockito.when(mock.findEmployeeByEmail(Mockito.anyString())).then(new Answer<Employee>() { @Override public Employee answer(InvocationOnMock invocation) throws Throwable { final String email = (String) invocation.getArguments()[0]; if(email == null) return null; if(email.startsWith("deep")) return employee; if(email.endsWith("packtpub.com")) return employee; return null; } }); final EmployeeController employeeController = new EmployeeController(mock); assertSame(employee, employeeController.findEmployeeByEmail("deep@gitshah.com")); assertSame(employee, employeeController.findEmployeeByEmail("deep@packtpub.com")); assertNull(employeeController.findEmployeeByEmail("hello@world.com")); } @Test public void shouldReturnCountOfEmployeesFromTheServiceWithDefaultAnswer() { EmployeeService mock = PowerMockito.mock(EmployeeService.class, new Answer() { @Override public Object answer(InvocationOnMock invocation) { return 10; } }); EmployeeController employeeController = new EmployeeController(mock); assertEquals(12, employeeController.getProjectedEmployeeCount()); }
注意要在头部导入:
import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer;
Answer接口指定执行的action和返回值执。 Answer的参数是InvocationOnMock的实例,支持:
callRealMethod():调用真正的方法
getArguments():获取所有参数
getMethod():返回mock实例调用的方法
getMock():获取mock实例
第一个测试方法根据不同情况构造不同返回。第2个测试方法设定调用返回的默认值。
使用spy进行部分模拟
现在调整类EmployeeService,拆分saveEmployee为方法:saveEmployee和createEmployee:
public void saveEmployee(Employee employee) { if(employee.isNew()) { createEmployee(employee); return; } employee.update(); } void createEmployee(Employee employee) { employee.setEmployeeId(EmployeeIdGenerator.getNextId()); employee.create(); WelcomeEmail emailSender = new WelcomeEmail(employee, "Welcome to Mocking with PowerMock How-to!"); emailSender.send(); }
EmployeeServiceTest类添加测试方法shouldInvokeTheCreateEmployeeMethodWhileSavingANewEmployee:
@Test public void shouldInvokeTheCreateEmployeeMethodWhileSavingANewEmployee() { final EmployeeService spy = PowerMockito.spy(new EmployeeService()); final Employee employeeMock = PowerMockito.mock(Employee.class); PowerMockito.when(employeeMock.isNew()).thenReturn(true); PowerMockito.doNothing().when(spy).createEmployee(employeeMock); spy.saveEmployee(employeeMock); Mockito.verify(spy).createEmployee(employeeMock); }
注意spy只能使用PowerMockito.doNothing()/doReturn()/doThrow()。
模拟私有方法
现在我们修改EmployeeService.createEmployee为private,在EmployeeServiceTest类添加如下方法:
@Test public void shouldInvokeTheCreateEmployeeMethodWhileSavingANewEmployee() { final EmployeeService spy = PowerMockito.spy(new EmployeeService()); final Employee employeeMock = PowerMockito.mock(Employee.class); PowerMockito.when(employeeMock.isNew()).thenReturn(true); PowerMockito.doNothing().when(spy).createEmployee(employeeMock); spy.saveEmployee(employeeMock); Mockito.verify(spy).createEmployee(employeeMock); }
模拟私有方法还有另外一种相对较复杂的方法,这里不做介绍了。
查看封装内容
添加 Department类
import java.util.ArrayList; import java.util.List; public class Department { private List<Employee> employees = new ArrayList<Employee>(); private long maxSalaryOffered; public void addEmployee(final Employee employee) { employees.add(employee); updateMaxSalaryOffered(); } /** * The private method that keeps track of * max salary offered by this department. */ private void updateMaxSalaryOffered() { maxSalaryOffered = 0; for (Employee employee : employees) { if(employee.getSalary() > maxSalaryOffered) { maxSalaryOffered = employee.getSalary(); } } } }
修改Employee类的如下方法:
public long getSalary() { return salary; } public void setSalary(int i) { salary = i; }
新建DepartmentTest类,添加如下测试方法:
import static org.junit.Assert.*; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.powermock.reflect.Whitebox; public class DepartmentTest { @Test public void shouldVerifyThatNewEmployeeIsAddedToTheDepartment() { final Department department = new Department(); final Employee employee = new Employee(); department.addEmployee(employee); final List<Employee> employees = Whitebox.getInternalState(department, "employees"); assertTrue(employees.contains(employee)); } @Test public void shouldAddNewEmployeeToTheDepartment() { final Department department = new Department(); final Employee employee = new Employee(); final ArrayList<Employee> employees = new ArrayList<Employee>(); Whitebox.setInternalState(department, "employees", employees); department.addEmployee(employee); assertTrue(employees.contains(employee)); } @Test public void shouldVerifyThatMaxSalaryOfferedForADepartmentIsCalculatedCorrectly() throws Exception { final Department department = new Department(); final Employee employee1 = new Employee(); final Employee employee2 = new Employee(); employee1.setSalary(60000); employee2.setSalary(65000); //Adding two employees to the test employees list. final ArrayList<Employee> employees = new ArrayList<Employee>(); employees.add(employee1); employees.add(employee2); Whitebox.setInternalState(department, "employees", employees); Whitebox.invokeMethod(department,"updateMaxSalaryOffered"); final long maxSalary = Whitebox.getInternalState(department, "maxSalaryOffered"); assertEquals(65000, maxSalary); } }
Whitebox.getInternalState(department, "employees")类似堆栈,查看变量的值。Whitebox.setInternalState(department, "employees",
employees)设置变量的值。 Whitebox.invokeMethod(department, "updateMaxSalaryOffered")调用方法。
更多参考:http://powermock.googlecode.com/svn/docs/powermock-1.5/apidocs/org/powermock/reflect/Whitebox.html。
禁用非预期行为
新增类BaseEntity:
public class BaseEntity { static { String x = null; x.toString(); } public BaseEntity() { throw new UnsupportedOperationException(); } protected void performAudit(String auditInformation) { throw new UnsupportedOperationException(); } }
修改类Department:
public class Department extends BaseEntity { private int departmentId; private String name; public Department(int departmentId) { super(); this.departmentId = departmentId; } public void setName(String name) { this.name = name; super.performAudit(this.name); } protected void performAudit(String auditInformation) { throw new UnsupportedOperationException(); } public Object getDepartmentId() { return departmentId; } public Object getName() { return name; } }
修改类DepartmentTest:
import static org.junit.Assert.*; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(Department.class) @SuppressStaticInitializationFor("BaseEntity") public class DepartmentTest { @Test public void shouldSuppressTheBaseConstructorOfDepartment() { PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class)); assertEquals(10, new Department(10).getDepartmentId()); } @Test public void shouldSuppressThePerformAuditMethodOfBaseEntity() { PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class)); PowerMockito.suppress(PowerMockito.method(BaseEntity.class, "performAudit", String.class)); final Department department = new Department(18); department.setName("Mocking with PowerMock"); assertEquals("Mocking with PowerMock", department.getName()); } @Test public void shouldSuppressTheInitializerForBaseEntity() { PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class)); assertNotNull(new Department(18)); } }
PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class));表示禁用BaseEntity的构造函数。PowerMockito.suppress(PowerMockito.constructor(BaseEntity.class, String.class, Integer.class))后面表示带字符串和整数参数。
PowerMockito.suppress(PowerMockito.method(BaseEntity.class, "performAudit", String.class))表示禁用BaseEntity的performAudit方法。
@SuppressStaticInitializationFor("BaseEntity")表示禁用BaseEntity的静态初始化。注意引号部分通常需要全名,比如"com.gitshah.powermock.BaseEntity"。
PowerMockito.suppress(PowerMockito.field(BaseEntity.class,"identifier")):禁用域。
参考资料
简明教程: https://github.com/jayway/powermock
https://github.com/jayway/powermock/wiki/MockitoUsage
https://www.ibm.com/developerworks/cn/java/j-lo-powermock/
书籍:Instant Mock Testing with PowerMock
作者博客:http://my.oschina.net/u/1433482 python测试开发精华群 291184506 PythonJava单元白盒测试 144081101