單元測試框架PowerMock
阿新 • • 發佈:2018-12-13
1.概述
Mockito 是一個針對 Java 的單元測試模擬框架,它與 EasyMock 和 jMock 很相似,都是為了簡化單元測試過程中測試上下文的搭建而開發的工具。
PowerMock 也是一個單元測試模擬框架,它是在其它單元測試模擬框架的基礎上做出的擴充套件。通過提供定製的類載入器以及一些位元組碼篡改技巧的應用,PowerMock 現了對靜態方法、構造方法、私有方法以及 Final 方法的模擬支援,對靜態初始化過程的移除等強大的功能。
2.引入依賴
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.8.5</version> </dependency>
3.程式碼示例
單元測試用到的類:
public interface StudentDao { String queryStudent(); } public interface StudentService { public String selectStudentByName(); public String selectStudentByName2(); } @Repository public class StudentDaoImpl implements StudentDao { @Override public String queryStudent() { return "拿著核武器的程式設計師"; } } @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentDao studentDao; // 正常方法 @Override public String selectStudentByName() { // 呼叫了私有方法 String student = getNameById(); System.out.println("method:selectStudentByName" + student); return student; } // 正常方法 @Override public String selectStudentByName2() { String name = StudentServiceImpl.selectStudentById(); System.out.println("靜態方法返回值:" + name); return name; } // 靜態方法 public static String selectStudentById() { System.out.println("------------------"); return "拿著大炮的男孩"; } private String getNameById() { String student = studentDao.queryStudent(); System.out.println("method:getNameById" + student); return student; } public final String getAgeById() { System.out.println("----------------"); return "拿著大炮的男孩"; } }
單元測試類:
@RunWith(PowerMockRunner.class) @PrepareForTest({ StudentServiceImpl.class }) public class StudentServiceTest { /** * spy()方法:表示區域性mock,執行方法的時候會進入具體的方法內,spy的作用是讓被測類正常工作,但是可以攔截某些方法的返回值 * 比如讓StudentServiceImpl中的selectStudentByName()正常工作,但是返回值可以是我們期望的值 * mock()方法:表示全域性mock,執行方法的時候不會進入到具體方法內 */ /** * 使用powermock的測試類需要加@RunWith(PowerMockRunner.class) * 若需要模擬建構函式、私有方法、static方法、final方法都需要在測試類上添加註解 * * @throws Exception * @PrepareForTest({ 被Mock的類 }) * * 1.測試私有方法 */ @Test public void test() throws Exception { // 區域性mock StudentServiceImpl serviceImpl = PowerMockito.spy(new StudentServiceImpl()); // 在selectStudentByName中呼叫了私有方法,此時需要對私有方法mock // 若有引數,就在後面使用Mockito.anyXxx() // 由於私有方法中又使用了自動注入的StudentDao,所以mock StudentDao然後通過Whitebox(白盒)替換屬性 StudentDao studentDao = PowerMockito.mock(StudentDao.class); // 第一個引數:需要被替換屬性的物件 ;第二個引數:屬性名 ; 第三個引數:屬性值 Whitebox.setInternalState(serviceImpl, "studentDao", studentDao); PowerMockito.doReturn("hahahaha").when(studentDao).queryStudent(); PowerMockito.when(serviceImpl, "getNameById").thenReturn("東皇太一"); serviceImpl.selectStudentByName(); } /** * 2.測試靜態方法 * 想要單元測試selectStudentByName2()方法,但是該方法中使用了靜態方法 */ @Test public void test2() { // 模擬靜態方法前需要先呼叫這一句,不寫會報錯!!! PowerMockito.mockStatic(StudentServiceImpl.class); // 模擬當執行靜態方法StudentServiceImpl.selectStudentById()時候,返回123(模擬的返回值) PowerMockito.when(StudentServiceImpl.selectStudentById()).thenReturn("123"); StudentServiceImpl serviceImpl = PowerMockito.spy(new StudentServiceImpl()); serviceImpl.selectStudentByName2(); } /** * 3.測試final方法 */ @Test public void test3() { StudentServiceImpl service = PowerMockito.mock(StudentServiceImpl.class); PowerMockito.when(service.getAgeById()).thenReturn("18"); String age = service.getAgeById(); System.out.println(age); } }