为什么JUnit中的规则通常定义为可变类型而非不可变类型?
问题解答
核心原因是JUnit 4的规则实现约束
- JUnit 4处理
@Rule注解的字段时,强制要求字段为public且非final。Kotlin的val编译为Java字节码后对应final字段,因此如果用@field:Rule标注val属性会直接触发运行时错误。 - 你示例中用的
@get:Rule是将注解标注到属性的getter方法而非字段本身,理论上可以搭配val使用。但早期Kotlin和JUnit 4的集成存在兼容坑,很多官方/社区示例统一用var是为了规避不同版本的兼容问题,属于广泛流传的最佳实践写法。
存在需要重新赋值规则的真实场景
最常见的是参数化测试场景:比如你要同一个测试用例适配多个Activity、不同的配置项,就可以在@Before预处理方法里,根据当前测试参数动态给规则变量赋值新的实例,无需拆分多个测试类,示例逻辑如下:
@RunWith(Parameterized::class) class MultiActivityTest { @get:Rule var activityRule: ActivityScenarioRule<out Activity>? = null @Parameterized.Parameter lateinit var activityClazz: Class<out Activity> @Before fun initRule() { activityRule = activityScenarioRule(activityClazz) } // 统一的测试逻辑,自动适配所有传入的Activity @Test fun testActivityLaunch() { activityRule?.scenario?.use { // 通用测试逻辑 } } companion object { @JvmStatic @Parameterized.Parameters fun provideActivities() = listOf( HomeActivity::class.java, SettingActivity::class.java, UserCenterActivity::class.java ) } }
不是必须写var的特殊情况
如果你确定不需要动态修改规则实例,且项目用的JUnit 4版本 >= 4.13,Kotlin版本 >= 1.4,完全可以用val搭配@get:Rule,运行不会有任何问题。很多老教程没更新这点,才会给人“Rule必须用var”的错觉。
内容的提问来源于stack exchange,提问作者SmallGrammer
相关产品推荐
相关产品推荐

