我有一个引用一些静态方法的文件:
class MyViewModel {
fun test() { }
companion object {
private val MY_STRING = ResourceGrabber.grabString(R.string.blah_blah)
}
}
在此文件的JUnit测试中,我编写了一些代码来模拟安装程序中的资源获取器。它将编译并运行,并且以下测试失败,正如我期望的那样:
@PrepareForTest(ResourceGrabber::class)
@RunWith(PowerMockRunner::class)
class MyViewModelTest {
private lateinit var viewModel: MyViewModel
@Before
fun setup() {
PowerMockito.mockStatic(ResourceGrabber::class.java)
val mockResourceGrabber = Mockito.mock(ResourceGrabber::class.java)
whenever(mockResourceGrabber.grabString(Mockito.anyInt())).thenAnswer { invocation ->
val res: Int? = invocation?.arguments?.get(0) as? Int
TestResourceGrabber.grabString(res)
}
viewModel = MyViewModel()
}
@Test
fun someTest() {
// Fails, as expected.
assertEquals(2, 3)
}
}
在这里事情变得怪异。我最近了解了自定义JUnit规则,可以使用这些规则来避免测试之间的某些重复代码。在这种情况下,我不需要将资源收集器工作复制并粘贴到使用它的每个测试套件中,因此我制定了一个自定义规则:
class ResourceGrabberRule : TestRule {
override fun apply(base: Statement?, description: Description?): Statement {
return object : Statement() {
override fun evaluate() {
PowerMockito.mockStatic(ResourceGrabber::class.java)
val mockResourceGrabber = Mockito.mock(ResourceGrabber::class.java)
whenever(mockResourceGrabber.grabString(Mockito.anyInt())).thenAnswer { invocation ->
val res: Int? = invocation?.arguments?.get(0) as? Int
TestResourceGrabber.grabString(res)
}
}
}
}
}
下面是该代码的实现。疯狂的事情是,无论什么情况,现在每个测试都通过了:
@PrepareForTest(ResourceGrabber::class)
@RunWith(PowerMockRunner::class)
class MyViewModelTest {
private lateinit var viewModel: MyViewModel
@Rule
@JvmField
val resourceGrabber = ResourceGrabberRule()
@Before
fun setup() {
viewModel = MyViewModel()
}
@Test
fun someTest() {
// PASSES!!!?!?!?!?!
assertEquals(2, 3)
}
}
我不确定问题出在哪里。我尝试从Android Studio和命令行构建和运行测试。我不知道我的规则实施不正确,还是与Powermock连接的JUnit规则存在问题,还是Kotlin批注处理存在问题。测试可以编译并运行,但是无论测试本身有什么内容都可以通过。
我愿意在这里对体系结构发表评论(我敢肯定社区中有很多人),但我确实在寻找有关我编写的规则为何能通过所有测试的解释。
答案 0 :(得分:2)
在自定义TestRule中,您需要调用base.evaluate()
来继续规则链https://github.com/junit-team/junit4/wiki/rules#custom-rules