mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-24 19:31:17 +08:00
add usage of verify void method
This commit is contained in:
parent
d75fdcd4e9
commit
fb62ab63cc
@ -4,7 +4,8 @@
|
||||
`TestableMock`是基于源码和字节码增强的Java单元测试辅助工具,包含以下功能:
|
||||
|
||||
- [访问被测类私有成员](zh-cn/doc/private-accessor.md):使单元测试能直接调用和访问被测类的私有成员,解决私有成员初始化和私有方法测试的问题
|
||||
- [快速Mock任意方法](zh-cn/doc/use-mock.md):使被测类的任意方法调用快速替换为Mock方法,实现"指哪换哪",解决传统Mock工具使用繁琐的问题
|
||||
- [快速Mock任意调用](zh-cn/doc/use-mock.md):使被测类的任意方法调用快速替换为Mock方法,实现"指哪换哪",解决传统Mock工具使用繁琐的问题
|
||||
- [辅助测试void方法](zh-cn/doc/test-void-method.md):利用Mock校验器对方法的内部逻辑进行检查,解决无返回值方法难以实施单元测试的问题
|
||||
|
||||
## 在Maven项目中使用
|
||||
|
87
docs/zh-cn/doc/test-void-method.md
Normal file
87
docs/zh-cn/doc/test-void-method.md
Normal file
@ -0,0 +1,87 @@
|
||||
测试无返回值的方法
|
||||
---
|
||||
|
||||
从功能的角度来说,虽然void方法不返回任何值,但它的执行一定会对外界产生某些"副作用",比如:
|
||||
|
||||
1. 初始化某些外部变量(私有成员变量或者全局静态变量)
|
||||
2. 在方法体内对外部对象实例进行赋值
|
||||
3. 输出了日志
|
||||
4. 调用了其他外部方法
|
||||
5. ... ...
|
||||
|
||||
|
||||
> 不返回任何值也不产生任何"副作用"的方法没有存在意义。
|
||||
|
||||
这些"副作用"归纳来说可分为两类:**修改外部变量**和**调用外部方法**。
|
||||
|
||||
通过TestableMock的私有字段访问和Mock校验器可以实现对这些操作的检查。
|
||||
|
||||
#### 修改外部变量的void方法
|
||||
|
||||
例如,下面这个方法会根据输入修改私有成员变量`hashCache`:
|
||||
|
||||
```java
|
||||
class Demo {
|
||||
private Map<String, Integer> hashCache = mapOf();
|
||||
|
||||
public void updateCache(String domain, String key) {
|
||||
String cacheKey = domain + "::" + key;
|
||||
Integer num = hashCache.get(cacheKey);
|
||||
hashCache.put(cacheKey, count == null ? initHash(key) : nextHash(num, key));
|
||||
}
|
||||
|
||||
... // 其他方法省略
|
||||
}
|
||||
```
|
||||
|
||||
若要测试此方法,可以利用TestableMock直接读取私有成员变量的值,对结果进行校验:
|
||||
|
||||
```java
|
||||
class DemoTest {
|
||||
private Demo demo = new Demo();
|
||||
|
||||
@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")); // 读取私有变量
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 调用外部方法的void方法
|
||||
|
||||
例如,下面这个方法会根据输入打印信息到控制台:
|
||||
|
||||
```java
|
||||
class Demo {
|
||||
public void recordAction(Action action) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss ");
|
||||
String timeStamp = df.format(new Date());
|
||||
System.out.println(timeStamp + "[" + action.getType() + "] " + action.getTarget());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若要测试此方法,可以利用TestableMock快速Mock掉`System.out.println`调用,然后用`InvokeVerifier.verify()`方法校验传入的打印内容:
|
||||
|
||||
```java
|
||||
class DemoTest {
|
||||
private Demo demo = new Demo();
|
||||
|
||||
// 拦截`System.out.println`调用
|
||||
@TestableMock
|
||||
public void println(PrintStream ps, String msg) {}
|
||||
|
||||
@Test
|
||||
public void testRecordAction() {
|
||||
Action action = new Action("click", ":download");
|
||||
demo.recordAction();
|
||||
// 验证Mock方法`println`被调用,且传入参数符合预期
|
||||
verify("println").matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} \\[click\\] :download");
|
||||
}
|
||||
}
|
||||
```
|
@ -21,14 +21,16 @@
|
||||
|
||||
> 当使用`testable-maven-plugin`插件时,应该移除`maven-surefire-plugin`插件上的TestableMock相关配置
|
||||
|
||||
相比而言,`testable-maven-plugin`插件能够与Jacoco插件直接同时使用,无需额外适配。但当通过IDE运行单个测试用例时,Mock功能会失效。
|
||||
`testable-maven-plugin`插件能够与Jacoco插件直接同时使用,无需额外适配,因此能使`pom.xml`文件编写起来更简单且美观。
|
||||
|
||||
这是由于IDE运行单个测试用例时只会运行`maven-surefire-plugin`插件,跳过了`testable-maven-plugin`插件执行,导致Mock功能所需的JavaAgent没有随测试启动。
|
||||
但是,当通过IDE运行单个测试用例时,Mock功能会失效。
|
||||
|
||||
这个问题可以通过配置IDE的测试参数绕过。以IntelliJ为例,在单元测试配置的"虚拟机参数(VM Option)"属性值末尾添加JavaAgent启动参数:`-javaagent:${HOME}/.m2/repository/com/alibaba/testable/testable-agent/x.y.z/testable-agent-x.y.z.jar`
|
||||
这是由于IDE运行单个测试用例时通常都只会运行`maven-surefire-plugin`插件,跳过了`testable-maven-plugin`插件执行,导致Mock功能所需的JavaAgent没有随测试注入。
|
||||
|
||||
该问题可以通过额外配置IDE的测试参数绕过。以IntelliJ为例,在单元测试配置的"虚拟机参数(VM Option)"属性值末尾添加JavaAgent启动参数:`-javaagent:${HOME}/.m2/repository/com/alibaba/testable/testable-agent/x.y.z/testable-agent-x.y.z.jar`
|
||||
|
||||
> PS:请将路径中的`x.y.z`替换成实际使用的版本号
|
||||
|
||||
![idea-vm-option](https://testable-code.oss-cn-beijing.aliyuncs.com/idea-vm-option.png)
|
||||
|
||||
由于需要在每个单测任务上分别配置,这种方法实际使用起来比较麻烦,因此目前依然优先推荐修改`maven-surefire-plugin`插件配置的方案。
|
||||
这样实际上还是该了`maven-surefire-plugin`插件的配置,因此目前除了需要考虑美观因素的场景以外,直接在`pom.xml`文件中修改`maven-surefire-plugin`插件配置依然是更加实用的方案。
|
||||
|
@ -1,11 +1,14 @@
|
||||
- 使用指南
|
||||
- [使用TestableMock](zh-cn/doc/usage.md)
|
||||
- 快速上手
|
||||
- [使用TestableMock](zh-cn/doc/setup.md)
|
||||
- [直接访问私有成员](zh-cn/doc/private-accessor.md)
|
||||
- [快速Mock任意方法](zh-cn/doc/use-mock.md)
|
||||
- [校验Mock调用](zh-cn/doc/matcher.md)
|
||||
- [测试无返回值的方法](zh-cn/doc/test-void-method.md)
|
||||
|
||||
- 使用参考
|
||||
- [校验Mock调用](zh-cn/doc/invoke-matcher.md)
|
||||
- [常见使用问题](zh-cn/doc/frequency-asked-questions.md)
|
||||
- [自助问题排查](zh-cn/doc/troubleshooting.md)
|
||||
- [Testable Maven插件](zh-cn/doc/use-maven-plugin.md)
|
||||
|
||||
- 其他文档
|
||||
- [Testable Maven插件](zh-cn/doc/use-maven-plugin.md)
|
||||
- [Release Note](zh-cn/doc/release-note.md)
|
||||
|
Loading…
Reference in New Issue
Block a user