Java中的PowerMock使用實(shí)踐
一、常用注解
@PrepareForTest和@RunWith是成對(duì)出現(xiàn)的,一般@RunWith(PowerMockRunner.class),@PrepareForTest的值是引用的靜態(tài)方法或私有方法的類。
@InjectMocks注解標(biāo)注的類會(huì)被注入所有被@Mock注解標(biāo)注的類。
@Before注解用于方法,表示在執(zhí)行@Test注解標(biāo)注的方法之前執(zhí)行。
在initMocks()方法中可以執(zhí)行MockitoAnnotations.initMocks(this);來(lái)將@Mock注解修飾的類注入到@InjectMocks修飾的類。
二、實(shí)例操作
首先定義三個(gè)類,分別是實(shí)體類Employee.java,數(shù)據(jù)操作類EmployeeDao.java,業(yè)務(wù)邏輯類EmployeeService.java,下面是3個(gè)類的具體定義:
public class Employee {
private String name;
private Double salary;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the salary
*/
public Double getSalary() {
return salary;
}
/**
* @param salary the salary to set
*/
public void setSalary(Double salary) {
this.salary = salary;
}
}EmployeeDao.java:
public interface EmployeeDao {
public Employee getEmployee(String name);
public boolean updateEmployee(Employee employee);
public static void deleteEmployee(String name) {
throw new NullPointerException();
}
public Exception saveEmployee(Employee employee);
}EmployeeService.java:
public class EmployeeServiceImpl {
private EmployeeDao employeeDao;
public EmployeeServiceImpl() {
}
public EmployeeServiceImpl(EmployeeDao employeeDao) {
this.employeeDao = employeeDao;
}
public Employee getEmployee(String name) {
return employeeDao.getEmployee(name);
}
public boolean updateEmployee(Employee employee) {
return employeeDao.updateEmployee(employee);
}
public boolean deleteEmployee(String name) {
try {
EmployeeDao.deleteEmployee(name);
return true;
} catch (Exception e) {
return false;
}
}
public boolean saveEmployee(Employee employee) {
try {
employeeDao.saveEmployee(employee);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}PowerMockito知識(shí)點(diǎn)
下面是測(cè)試類中涉及到的PowerMockito知識(shí)點(diǎn):
1)其中涉及到靜態(tài)方法,因此需要使用@RunWith(PowerMockRunner.class)
@PrepareForTest({ EmployeeDao.class })注解,PrepareForTest的值是靜態(tài)方法所在的類或接口,否則會(huì)報(bào)下面的錯(cuò)誤:
org.powermock.api.mockito.ClassNotPreparedException: The class mock.EmployeeDao not prepared for test. To prepare this class, add class to the '@PrepareForTest' annotation. In case if you don't use this annotation, add the annotation on class or method level. at org.powermock.api.mockito.expectation.reporter.MockitoPowerMockReporter.classNotPrepared(MockitoPowerMockReporter.java:32)
2)使用@Before注解在調(diào)用@Test注解的方法之前進(jìn)行初始化,比如使用mock(類的Class對(duì)象)來(lái)創(chuàng)建需要模擬的對(duì)象,這樣我們就可以假設(shè)被模擬的對(duì)象已經(jīng)實(shí)現(xiàn),盡管他其實(shí)是一個(gè)沒(méi)有實(shí)現(xiàn)類的接口。
3)在模擬對(duì)象創(chuàng)建之后,我們就可以使用when(調(diào)用模擬對(duì)象的方法).thenReturn(定義方法調(diào)用的返回值),這樣我們就相當(dāng)于假設(shè)調(diào)用被模擬對(duì)象的方法后返回的一直是thenReturn中定義的值。這樣我們就不用關(guān)心被模擬對(duì)象的實(shí)現(xiàn)按,只關(guān)心下面我們測(cè)試的業(yè)務(wù)邏輯是否存在問(wèn)題。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ EmployeeDao.class })
public class EmployeeServiceImplTest {
@Mock
public EmployeeDao employeeDao;
@Mock
EmployeeServiceImpl employeeServiceImpl;
// @Before注解的方法會(huì)在調(diào)用測(cè)試方法前執(zhí)行初始化動(dòng)作
@Before
public void initMocks() {
// 創(chuàng)建模擬對(duì)象EmployeeDao的實(shí)例
employeeDao = mock(EmployeeDao.class);
// 將模擬對(duì)象賦給業(yè)務(wù)類實(shí)例
employeeServiceImpl = new EmployeeServiceImpl(employeeDao);
}
@Test
public void getEmployeeTest() {
String name = "scott";
Employee employee = new Employee();
employee.setName("scott");
employee.setSalary(8888.0);
// 定義當(dāng)執(zhí)行employeeDao.getEmployee(name)方法時(shí)始終返回employee對(duì)象,相當(dāng)于實(shí)現(xiàn)了employeeDao的這個(gè)方法
when(employeeDao.getEmployee(name)).thenReturn(employee);
/*
* 下面測(cè)試我們想要單元測(cè)試的employeeServiceImpl.getEmployee(name)方法 我們已經(jīng)屏蔽了該方法對(duì)employeeDao.getEmployee(name)的調(diào)用,相當(dāng)于解除了依賴
* 這樣我們只需要關(guān)心employeeServiceImpl.getEmployee(name)方法的邏輯是否存在問(wèn)題
*/
Employee employee2 = employeeServiceImpl.getEmployee(name);
System.out.println(employee2.getSalary());
}
@Test
public void updateEmployeeTest() {
Employee employee = new Employee();
employee.setName("tiger");
employee.setSalary(99999.0);
when(employeeDao.updateEmployee(anyObject())).thenReturn(true);
Employee employee2 = new Employee();
employee.setName("scott");
employee.setSalary(99999.0);
Boolean boolean1 = employeeServiceImpl.updateEmployee(employee2);
System.out.println(boolean1);
}
@Test
public void deleteEmployeeTest() {
String name = "haha";
// 因?yàn)檫@里調(diào)用的是靜態(tài)方法,因此使用PowerMockito.mockStatic(EmployeeDao.class);來(lái)模擬靜態(tài)類
PowerMockito.mockStatic(EmployeeDao.class);
// 使用doNothing()定義執(zhí)行下面一句語(yǔ)句時(shí)什么也不做
PowerMockito.doNothing().when(EmployeeDao.class);
// 這一句由于上面的doNothing()即使會(huì)拋異常也不會(huì)再拋
EmployeeDao.deleteEmployee(name);
// 因此employeeServiceImpl.deleteEmployee(name)執(zhí)行時(shí)也沒(méi)有發(fā)現(xiàn)異常返回true
EmployeeServiceImpl employeeServiceImpl = new EmployeeServiceImpl();
Assert.assertTrue(employeeServiceImpl.deleteEmployee(name));
}
@Test
public void throwDeleteExceptionTest() {
String name = "haha";
PowerMockito.mockStatic(EmployeeDao.class);
// doThrow()定義下面一句語(yǔ)句會(huì)拋出異常
PowerMockito.doThrow(new NullPointerException()).when(EmployeeDao.class);
EmployeeDao.deleteEmployee(name);
// 因此employeeServiceImpl.deleteEmployee(name)執(zhí)行會(huì)返回false
EmployeeServiceImpl employeeServiceImpl = new EmployeeServiceImpl();
assertTrue(employeeServiceImpl.deleteEmployee(name));
}
@Test
public void saveEmployeeTest() {
Employee employee = new Employee();
employee.setName("scott");
employee.setSalary(8888.0);
// 打樁,定義方法返回的值
when(employeeDao.saveEmployee(employee)).thenReturn(new NullPointerException());
// 這里doNothing()沒(méi)有生效,原因是這里調(diào)用的是實(shí)例方法,不是靜態(tài)方法
PowerMockito.doNothing().when(employeeDao).saveEmployee(employee);
employeeServiceImpl.saveEmployee(employee);
}
@Test
public void throwSaveEmployeeTest() {
Employee employee = new Employee();
employee.setName("scott");
employee.setSalary(8888.0);
when(employeeDao.saveEmployee(employee)).thenReturn(new NullPointerException());
// 這里的doThrow()實(shí)際沒(méi)有生效,因?yàn)檫@里調(diào)用的是實(shí)例方法,不是靜態(tài)方法,因此不存在使下一句語(yǔ)句拋異常的作用
PowerMockito.doThrow(new NullPointerException()).when(employeeDao).saveEmployee(employee);
employeeServiceImpl.saveEmployee(employee);
}
}到此這篇關(guān)于Java中的PowerMock使用實(shí)踐的文章就介紹到這了,更多相關(guān)PowerMock使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
eclipse導(dǎo)入IntelliJ IDEA的maven項(xiàng)目的示例
本篇文章主要介紹了eclipse導(dǎo)入IntelliJ IDEA的maven項(xiàng)目的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
詳解Springboot Oauth2 Server搭建Oauth2認(rèn)證服務(wù)
這篇文章主要介紹了Springboot Oauth2 Server 搭建Oauth2認(rèn)證服務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
Spring Security組件一鍵接入驗(yàn)證碼登錄和小程序登錄的詳細(xì)過(guò)程
這篇文章主要介紹了Spring Security 一鍵接入驗(yàn)證碼登錄和小程序登錄,簡(jiǎn)單介紹一下這個(gè)插件包的相關(guān)知識(shí),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-04-04
SpringCloud Gateway的路由,過(guò)濾器和限流解讀
這篇文章主要介紹了SpringCloud Gateway的路由,過(guò)濾器和限流解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
Java構(gòu)造函數(shù)里的一些坑記錄super()和this()
這篇文章主要介紹了Java構(gòu)造函數(shù)里的一些坑記錄super()和this(),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
Java 基于AQS實(shí)現(xiàn)一個(gè)同步器
這篇文章主要介紹了如何基于AQS實(shí)現(xiàn)一個(gè)同步器,幫助大家更好的理解和學(xué)習(xí)Java并發(fā),感興趣的朋友可以了解下2020-09-09

