3.6 KiB
使用MockWith注解
@MockWith
注释的功能是为测试显式指定Mock容器,通常用于测试类或Mock容器类没有在标准约定位置的情况,以下列举几种典型使用场景。
1. 非标准位置的Mock容器类
TestableMock
会依次在以下两个位置寻找Mock容器:
- 测试类中名为
Mock
的静态内部类(譬如原类型是Demo
,测试类是DemoTest
,Mock容器类为DemoTest.Mock
) - 同包路径下寻找名为
被测类+Mock
的外部类(譬如原类型是Demo
,测试类是DemoTest
,Mock容器类为DemoMock
)
倘若实际要使用的Mock容器类不在这两个位置,就需要在测试类上使用@MockWith
注释了。一般来说,造成Mock容器类不在默认位置的原因可能有两种:复用Mock容器、集中管理Mock容器。
当对一批功能近似的类型进行测试的时候,由于需要进行Mock的外部调用基本一致,可以将这些类型所需的所有Mock方法集中写在一个Mock容器类里,然后让相关测试类共同引用这个公共Mock容器。详见复用Mock类与方法文档。
另一种情况是开发者希望将Mock方法的定义与测试类本身分开,以便进行集中管理(或规避某些扫描工具的路径规则),譬如形成下面这种目录结构:
src/
main/
com/
demo/
service/
DemoService.java
test/
com/
demo/
service/
DemoServiceTest.java
mock/
service/
DemoServiceMock.java
此时就需要在测试类上显式的指定相应的Mock容器类了,这种场景在实际情况中比较少见。
2. 非标准位置的测试类
TestableMock
在建立“被测类”、“测试类”、“Mock容器类”之间关联的过程中,为了识别被测类的位置,约定测试类应当与被测类在相同的包路径,且名称为被测类+Test
。当实际情况不符合这种约定的时候,就需要通过在被测类上添加@MockWith
注解来显式的建立关联。例如:
@MockWith(ServiceTest.Mock.class)
public class DemoService {
...
}
public class ServiceTest {
public static class Mock extends BasicMock {
...
}
}
注意:
@MockWith
注解通常是使用在测试类上,但这种情况下需要用在被测类上@MockWith
指向的目标始终是Mock容器类,而不是测试类@MockWith
默认使用被注解类名字的尾缀判断当前类是被测类(名字非Test
结尾)还是测试类(名字Test
结尾),若遇到不符合此规则的类型,应使用注解的treatAs
参数显式的指定(ClassType.SourceClass
-被测类/ClassType.TestClass
-测试类)
更进一步来说,若出现测试类与Mock容器类均不在约定位置的时候,则需要同时在测试类与被测类上都使用@MockWith
指向同一个Mock容器类来建立三者的关联,但这种场景在实际运用中很少会遇到。
3. 使用不包含Mock方法的Mock容器类
为了加快搜索Mock容器类的速度,在扫描过程中,TestableMock
只会将自身定义有Mock方法(包含@MockMethod
或@MockMockConstructor
注解的方法)以及明确被@MockWith
指向的类识别为有效的Mock容器,而不会去遍历其父类。
对于某些特殊情况,譬如希望将实际Mock方法均定义在父类,实际使用的子容器仅仅重载父类的某些特定方法,此时即使Mock容器类的位置符合约定,为了能够被识别,依然应该在相应的测试类上增加对Mock容器类的@MockWith
引用。