alibaba.teastable 测试入门
1. pom 配置
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>5.6.2</junit.version>
<testable.version>0.6.10</testable.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-all</artifactId>
<version>${testable.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>@{argLine} -javaagent:${settings.localRepository}/com/alibaba/testable/testable-agent/${testable.version}/testable-agent-${testable.version}.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
2. mock环境
测试类和被测试类一定要在同一个包下,并且类名一定是<被测试类>Test
如被测试类是 src/main/java/com.alibaba.demo.basic.DemoInherit
那么测试类应该是 src/test/java/com.alibaba.demo.basic.DemoInheritTest
否则mock的方法将无法生效
在被测试类中写一个静态内部类Mock,将需要mock的方法放在Mock中,如下:
class DemoInheritTest {
private DemoInherit demoInherit = new DemoInherit();
public static class Mock {
@MockInvoke(targetMethod = "put")
private void put_into_box(Box self, String something) {
self.put("put_" + something + "_into_box");
}
@MockInvoke(targetMethod = "put")
private void put_into_blackbox(BlackBox self, String something) {
self.put("put_" + something + "_into_blackbox");
}
@MockInvoke(targetMethod = "get")
private String get_from_box(Box self) {
return "get_from_box";
}
// 要覆写的构造函数签名为`BlackBox(String)`
// Mock方法返回`BlackBox`类型对象,方法的名称随意起
@MockContructor
private BlackBox createBlackBox(String text) {
return new BlackBox("mock_" + text);
}
}
}
- 实际规则约定归纳起来只有两条:
Mock非构造方法,拷贝原方法定义到Mock容器类,加@MockMethod注解
Mock构造方法,拷贝原方法定义到Mock容器类,返回值换成构造的类型,方法名随意,加@MockContructor注解 - 如果需要修改成员变量
直接使用PrivateAccessor.set
3. 写测试逻辑
测试逻辑比较简单,修改方法内部使用到的外部参数,或者修改方法调用值,调用被测方法,校验方法副作用
@Test
public void testTimeRange() {
// 调用私有方法
UserDTO t = PrivateAccessor.invoke(userService, "syncFromPdd", "1068", "123", new PopShop(), 1);
// 调用 非私有方法
BlackBox box = (BlackBox)demoInherit.putIntoBox();
}
4. 校验返回值或者“副作用”
不返回任何值也不产生任何"副作用"的方法没有存在的意义
- 测试返回值
@Test
void should_mock_call_sub_object_method_by_sub_object() {
BlackBox box = demoInherit.putIntoBlackBox();
assertEquals("put_data_into_blackbox", box.get());
}
- 校验副作用
- 修改外部变量
- 调用外部方法
@Test
public void testSaveToCache() {
Integer firstVal = demo.initHash("hello"); // 访问私有方法
Integer nextVal = demo.nextHash(firstVal, "hello"); // 访问私有方法
// 调用无返回值方法
demo.saveToCache("demo", "hello");
// 读取私有变量校验副作用
assertEquals(firstVal, demo.hashCache.get("demo::hello")); // 读取私有变量
demo.saveToCache("demo", "hello");
assertEquals(nextVal, demo.hashCache.get("demo::hello")); // 读取私有变量
}