testable-mock/docs/zh-cn/doc/frequently-asked-questions.md
2021-03-16 22:19:16 +08:00

3.7 KiB
Raw Blame History

常见使用问题

1. 如何初始化被测类中通过@Autowired@Resource注入的私有字段?

若该对象的方法在测试时需要被Mock则无需初始化。

若测试运行时需用到该对象的真实调用,则可以在测试类的构造方法内直接创建对象,然后利用TestableMock访问私有成员的能力给这些字段赋值。

对于JUnit框架还可以使用@RunWith(SpringRunner.class)注解将Spring上下文启动起来然后在测试类里用@Resource把需要依赖对象注入进来,再利用PrivateAccessor赋值给被测类的私有字段。

2. TestableMock是否能够与其他Mock工具一起使用

TestableMock可与其他基于动态代理机制的Mock工具安全的共同使用譬如MockitoSpockEasyMock等皆属此范畴。

对于会修改类加载器或被测类字节码的Mock工具譬如PowerMockJMockit,尚无案例证明会与TestableMock发生冲突,但从原理来说二者可能存在不兼容风险,请谨慎使用。

3. 父类变量指向子类对象时如何实现Mock方法

在代码中,经常会有使用接口变量或父类变量指向子类实例,调用父类或子类方法的情况。

这时候遵循一个原则Mock方法的首个参数类型始终与发起调用的变量类型一致

因此不论实际被调用方法来自父类还是子类也不论子类是否覆写该方法。若发起调用的变量为父类型或接口类型则Mock方法的首个参数类型都应该使用相应的父类或接口类型。

参见Java和Kotlin示例中DemoInheritTest测试类的用例。

4. 如何Mock对于泛型方法(模板方法)

与普通方法的Mock方法相同直接在Mock方法上使用相同的泛型参数即可。

参见Java和Kotlin示例中DemoTemplateTest测试类的用例。

由于JVM存在泛型擦除机制对于Java项目也可以直接使用Object类型替代泛型参数见Java版DemoTemplateTest测试类中被注释掉的"第二种写法"示例。

5. 如何Mock在内部类代码里的调用

在其所在外部类对应的Mock容器中定义所需的Mock方法即可。

参见Java和Kotlin示例中DemoInnerClass测试类的用例。

6. 在Kotlin项目对String类中的方法进行Mock不生效

Kotlin语言中的String类型实际上是kotlin.String,而非java.lang.String。但在构建生成自字节码的时候又会被替换为Java的java.lang.String因此无论将Mock目标写为kotlin.Stringjava.lang.String均无法正常匹配到原始的被调用方法。

实际场景中需要对String类中的方法进行Mock的场景很少TestableMock暂未对这种情况做特别处理。

7. TestableMock能否用于Android项目的测试

结合Roboelectric测试框架可使用。

Android系统的DalvikART虚拟机采用了与标准JVM不同的字节码体系会影响TestableMock的正常工作。Roboelectric框架能在普通JVM虚拟机上运行Android单元测试其速度比通过Android虚拟机运行单元测试快非常多绝大多数Android App的单元测试都在使用Roboelectric框架。

8. 在IntelliJ运行测试报"Command Line is too Long. Shorten command line for ..."错误?

这个问题是由于系统ClassPath包含太多路径所致与是否使用TestableMock无关。但需要注意的是IntelliJ提供了两种辅助解决机制JAR manifestclasspath file,若测试中使用了TestableMock,请选择JAR manifest

jar-manifest