Kotlin测试中如何让setUp仅执行一次?遇未解析引用问题求助
解决Android测试中的两个问题:setUp仅执行一次 + 子类访问父类activityRule报错
我来帮你逐个搞定这两个测试中的小麻烦:
问题1:子类访问父类activityRule报「Unresolved reference」错误
这是Kotlin的默认访问权限在搞鬼——类的成员属性默认是private的,所以子类根本看不到父类的activityRule。只需要把父类的activityRule改成protected修饰,子类就能正常访问了:
修改你的BaseTest类:
@RunWith(AndroidJUnit4::class) @LargeTest open class BaseTest { @Rule protected val activityRule = ActivityTestRule(HomeActivity::class.java) }
这样子类里的activityRule引用就不会再报错啦。
问题2:让setUp函数仅执行一次,而非每个测试用例前都运行
JUnit的@Before注解本来就是在每个测试方法执行前都跑一遍,要实现只执行一次的初始化逻辑,有两种靠谱方案:
方案1:用标志位控制初始化逻辑仅执行一次
在测试类里加个静态的布尔标志,判断初始化逻辑是否已经执行过,只在第一次进入setUp时执行核心操作:
@RunWith(AndroidJUnit4::class) @LargeTest open class HomeScreenWithoutInternet : BaseTest() { private lateinit var context: HomeActivity // 静态标志位,记录是否已完成初始化 companion object { private var isSetUpCompleted = false } @Before open fun setUp() { if (!isSetUpCompleted) { context = activityRule.activity val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager wifiManager.isWifiEnabled = false TimeUnit.SECONDS.sleep(5) assertFalse("There is internet connection available", isConnected(context)) // 标记初始化完成,后续不再执行 isSetUpCompleted = true } } }
这种方案的好处是不用改ActivityTestRule的定义,保持实例级别的规则,能避免测试用例之间的状态污染。
方案2:使用@BeforeClass实现类级别的初始化
如果你的测试用例之间不需要隔离Activity状态,可以用@BeforeClass注解(对应类级别的初始化,仅在所有测试方法执行前运行一次),但要注意几个细节:
@BeforeClass必须是静态方法(Kotlin中需要用@JvmStatic配合companion object)ActivityTestRule需要改成静态的类级规则(用@ClassRule和@JvmField)
先修改BaseTest:
@RunWith(AndroidJUnit4::class) @LargeTest open class BaseTest { companion object { @ClassRule @JvmField val activityRule = ActivityTestRule(HomeActivity::class.java) } }
再修改子类的初始化逻辑:
@RunWith(AndroidJUnit4::class) @LargeTest open class HomeScreenWithoutInternet : BaseTest() { companion object { private lateinit var context: HomeActivity @BeforeClass @JvmStatic fun setUpOnce() { context = activityRule.activity val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager wifiManager.isWifiEnabled = false TimeUnit.SECONDS.sleep(5) assertFalse("There is internet connection available", isConnected(context)) } } }
⚠️ 注意:这种方案下所有测试方法会共享同一个Activity实例,如果测试用例之间需要干净的初始状态,更推荐用方案1。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

