testable-mock/docs/Usage.md

3.9 KiB
Raw Blame History

使用说明

引入Testable

首先在项目pom.xml文件中添加testable-processor依赖:

<dependency>
    <groupId>com.alibaba.testable</groupId>
    <artifactId>testable-processor</artifactId>
    <version>${testable.version}</version>
    <scope>provided</scope>
</dependency>

此时项目就获得了在单元测试中随意访问被测类私有字段和方法的能力(需配合注解使用,见下文详述)。

若要开启极速Mock功能还需在pom.xml里加上testable-maven-plugin插件。

<plugin>
    <groupId>com.alibaba.testable</groupId>
    <artifactId>testable-maven-plugin</artifactId>
    <version>${testable.version}</version>
    <executions>
        <execution>
            <id>prepare</id>
            <goals>
                <goal>prepare</goal>
            </goals>
        </execution>
    </executions>
</plugin>

使用Testable

Testable目前能为测试类提供两项增强能力:直接访问被测类的私有成员极速Mock被测方法中的调用

访问私有成员字段和方法

只需为测试类添加@EnablePrivateAccess注解,即可在测试用例中获得以下增强能力:

  • 调用被测类的私有方法
  • 读取被测类的私有成员
  • 修改被测类的私有成员
  • 修改被测类的常量成员使用final或static final修饰的成员

访问和修改私有、常量成员时IDE可能会提示语法有误但编译器将能够正常运行测试。

若不希望看到IDE的语法错误提醒或是在基于JVM的非Java语言项目里譬如Kotlin语言也可以借助PrivateAccessor工具类来实现私有成员的访问。

效果见示例项目文件DemoServiceTest.java中的should_able_to_mock_private_method()should_able_to_mock_private_field()测试用例。

Mock被测类的任意方法调用

【1】覆写任意类的方法调用

在测试类里定义一个有@TestableMock注解的普通方法,使它与需覆写的方法名称、参数、返回值类型完全一致,然后在其参数列表首位再增加一个类型为该方法原本所属对象类型的参数。

此时被测类中所有对该需覆写方法的调用将在单元测试运行时将自动被替换为对上述自定义Mock方法的调用。

注意:当遇到有两个需覆写的方法重名时,可将需覆写的方法名写到@TestableMock注解的targetMethod参数里此时Mock方法自身就可以随意命名了。

示例项目文件DemoServiceTest.java中的should_able_to_mock_common_method()用例详细展示了这种用法。

【2】覆写被测类自身的成员方法

有时候在对某些方法进行测试时希望将被测类自身的另外一些成员方法Mock掉。

操作方法与前一种情况相同Mock方法的第一个参数类型需与被测类相同即可实现对被测类自身不论是公有或私有成员方法的覆写。

详见示例项目文件DemoServiceTest.java中的should_able_to_mock_member_method()用例。

【3】覆写任意类的new操作

在测试类里定义一个有@TestableMock注解的普通方法,将注解的targetMethod参数写为"",然后使该方法与要被创建类型的构造函数参数、返回值类型完全一致,方法名称随意。

此时被测类中所有用new创建指定类的操作并使用了与Mock方法参数一致的构造函数将被替换为对该自定义方法的调用。

详见示例项目文件DemoServiceTest.java中的should_able_to_mock_new_object()用例。

【4】识别当前测试用例和调用来源

在Mock方法中可以通过TestableTool.TEST_CASETestableTool.SOURCE_METHOD来识别当前运行的测试用例名称进入该Mock方法前的被测类方法名称,从而区分处理不同的调用场景。

详见示例项目文件DemoServiceTest.java中的should_able_to_get_source_method_name()should_able_to_get_test_case_name()用例。