【发布时间】:2020-12-06 06:07:32
【问题描述】:
我有以下单元测试成功通过:
@Mock
private lateinit var resource: Observer<Resource<List<User>>>
@Captor
private lateinit var captor: ArgumentCaptor<Resource<List<User>>>
@Test
fun givenServerResponse200_whenFetch_shouldReturnSuccess() {
mockkStatic("com.android.sample.util.ContextExtKt")
every {
context.isNetworkAvailable()
} returns true
val repository = MainRepository(api)
val viewModel = MainViewModel(repository, context).apply {
state.asLiveData().observeForever(resource)
}
testCoroutineRule.runBlockingTest {
`when`(api.getUsers()).thenReturn(emptyList())
viewModel.userIntent.send(MainIntent.FetchUser)
}
try {
verify(resource, times(3)).onChanged(captor.capture())
verify(resource).onChanged(Resource.Success(emptyList()))
} finally {
viewModel.state.asLiveData().removeObserver(resource)
}
}
如您所见,我们与资源进行了 3 次交互。这是一个资源类:
sealed class Resource<out T> {
class Idle<out T> : Resource<T>()
class Loading<out T> : Resource<T>()
data class Success<out T>(val data: T?) : Resource<T>()
data class Failure<out T>(val message: String?) : Resource<T>()
}
现在我在单元测试中添加以下验证:
verify(resource).onChanged(Resource.Idle())
verify(resource).onChanged(Resource.Loading())
我收到以下错误消息:
Wanted but not invoked:
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Idle@ddf20fd
);
-> at com.android.sample.easymarkets.MainViewModelTest.givenServerResponse200_whenFetch_shouldReturnSuccess(MainViewModelTest.kt:69)
However, there were exactly 3 interactions with this mock:
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Idle@34cf5a97
);
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Loading@5b3f3ba0
);
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
resource.onChanged(Success(data=[]));
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
Wanted but not invoked:
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Idle@ddf20fd
);
-> at com.android.sample.easymarkets.MainViewModelTest.givenServerResponse200_whenFetch_shouldReturnSuccess(MainViewModelTest.kt:69)
However, there were exactly 3 interactions with this mock:
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Idle@34cf5a97
);
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
resource.onChanged(
com.android.sample.easymarkets.util.Resource$Loading@5b3f3ba0
);
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
resource.onChanged(Success(data=[]));
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
at com.android.sample.easymarkets.MainViewModelTest.givenServerResponse200_whenFetch_shouldReturnSuccess(MainViewModelTest.kt:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at com.android.sample.easymarkets.TestCoroutineRule$apply$1.evaluate(TestCoroutineRule.kt:23)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
【问题讨论】: