使用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 {}</pre>
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); } }</pre>
注意如果上述代碼出現莫名其妙的錯誤,建議先確認所有文件已經保存,再不行重啟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()); } }</pre>
@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(); } }</pre>
注意這里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實例
</ul>
第一個測試方法根據不同情況構造不同返回。第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(); } } } }</pre>
修改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); } }</pre>
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(); } }</pre>
修改類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; } }</pre>
修改類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)); } }</pre>
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