如果需要临时将一个对象的内部对象替换为 mock 对象,在无法通过set和get处理内部对象的情况下,可以利用反射搞定。
Java JOOR 反射库(Java JOOR 反射库)是一个很好用的反射库。本文用它进行临时替换。
用一个小项目作为示例:
项目结构:
.
├── build.gradle
├── settings.gradle
└── src
├── main
│ ├── java
│ │ └── demo
│ │ ├── HttpService.java
│ │ └── BizService.java
│ └── resources
└── test
├── java
│ └── demo
│ └── BizServiceTest.java
└── resources
build.gradle 中声明的依赖:
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.25.1'
testCompile group: 'org.jooq', name: 'joor-java-8', version: '0.9.7'
}
HttpService 类:
package demo;
public class HttpService {
public int queryStatus() {
// 发起网络请求,提取返回结果
// 这里直接返回0
return 0;
}
}
BizService 类:
package demo;
public class BizService {
private HttpService httpService = new HttpService();
public String hello() {
int status = httpService.queryStatus();
if (status == 0) {
return "你好";
}
else if (status == 1) {
return "Hello";
}
else {
return "未知状态";
}
}
}
BizServiceTest 测试类:
package demo;
import org.joor.Reflect;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class BizServiceTest {
private BizService bizService = new BizService();
@Test
public void testHello() {
System.out.println( bizService.hello() ); // 输出'你好'
// 取出原有的对象
Object realHttpService = Reflect.on(bizService).get("httpService");
// 创建 mock 对象,并用它替换掉 bizService 中的 httpService 对象
HttpService mockHttpService = mock(HttpService.class);
when(mockHttpService.queryStatus()).thenReturn(1);
Reflect.on(bizService).set("httpService", mockHttpService);
System.out.println( bizService.hello() ); // 输出'hello'
// 再将原先的对象设置回去
Reflect.on(bizService).set("httpService", realHttpService);
System.out.println( bizService.hello() ); // 输出'你好'
}
}