У меня есть файл, который ссылается на некоторые статические методы:
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, так и из командной строки. Я не знаю, правильно ли я реализовал свое правило, или это проблема с правилом JUnit, связанным с Powermock, или это проблема с обработкой аннотаций Kotlin. Тесты компилируются и запускаются, но просто проходят независимо от того, что находится внутри самих тестов.
Я открыт для комментариев об архитектуре здесь (я уверен, что у сообщества есть много), но я действительно ищу объяснение того, почему написанное мной правило проходит каждый тест.