【问题标题】:How to resolve .AssertionError: Verification failed如何解决.AssertionError:验证失败
【发布时间】:2021-09-09 12:38:06
【问题描述】:

我正在为 viewModel 编写一个单元测试,它有一个 liveData,我正在创建一个观察者并检查数据,但我不确定我的做法是否正确

我收到此错误:

java.lang.AssertionError: Verification failed: call 1 of 1: Observer(#2).onChanged(eq(Success([Character(name=myName, img=image, occupation=[], status=status, nickname=nickName, appearance=[])])))) was not called

    at io.mockk.impl.recording.states.VerifyingState.failIfNotPassed(VerifyingState.kt:66)
    at io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:42)
    at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:60)
    at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalCoVerify(API.kt:143)
    at io.mockk.MockKKt.coVerify(MockK.kt:175)
    at io.mockk.MockKKt.coVerify$default(MockK.kt:172)
    at com.example.breakingbad.MainActivityViewModelTest$fetchCharacters$1.invokeSuspend(MainActivityViewModelTest.kt:69)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.test.TestCoroutineDispatcher.dispatch(TestCoroutineDispatcher.kt:50)
    at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:322)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
    at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
    at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
    at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
    at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
    at com.example.breakingbad.MainActivityViewModelTest.fetchCharacters(MainActivityViewModelTest.kt:56)

ViewModelTest

//@RunWith(MockitoJUnitRunner::class)

@ExperimentalCoroutinesApi
class MainActivityViewModelTest {

    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    private val testDispatcher = TestCoroutineDispatcher()
    private val testCoroutineScope = TestCoroutineScope(testDispatcher)

    private val dataRepository: DataRepository = mockk(relaxed = true)

    private val mainActivityViewModel = MainActivityViewModel(dataRepository)

//    @Mock
//    private lateinit var dataObserver: Observer<Result<List<Character>>>

    private var dataObserver: Observer<Result<List<Character>>> = mockk()

    @Before
    fun setUp() {
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun cleanup() {
        Dispatchers.resetMain()
        testCoroutineScope.cleanupTestCoroutines()
    }

    @Test
    fun fetchCharacters() {
        testCoroutineScope.launch {
            coEvery { dataRepository.getCharacters() } returns Result.success(arrayListOf(Character(
                    name = "myName",
                    img = "image",
                    occupation = arrayListOf(),
                    status = "status",
                    nickname = "nickName",
                    appearance = arrayListOf()
            )))

            mainActivityViewModel.fetchCharacters()
            coVerify { dataRepository.getCharacters() }

            coVerify { dataObserver.onChanged(
                    Result.success(listOf(Character (
                            name = "myName",
                            img = "image",
                            occupation = arrayListOf(),
                            status = "status",
                            nickname = "nickName",
                            appearance = arrayListOf()
                    )))
            ) }
            mainActivityViewModel.charactersLiveData.removeObserver(dataObserver)
        }
    }
}

视图模型

class MainActivityViewModel @Inject constructor(
        private val dataRepository: DataRepository
): ViewModel() {
    private val _charactersLiveData = MutableLiveData<Result<ArrayList<Character>>>()
    val charactersLiveData: LiveData<Result<ArrayList<Character>>> = _charactersLiveData

    fun fetchCharacters() {
        viewModelScope.launch(Dispatchers.IO) {
            _charactersLiveData.postValue(dataRepository.getCharacters())
        }
    }
}

【问题讨论】:

    标签: android kotlin junit mockk


    【解决方案1】:

    coVerify 断言调用了一个函数,而错误告诉你该函数没有被调用。

    您似乎在测试类中将dataObserver 声明为模拟,但实际上您并没有对它做任何事情。简单地在你的测试类中声明它并不能让它观察charactersLiveData——这就是你似乎假设它正在做的事情。你不希望它是一个模拟 - 你希望它是一个对实时数据做出反应的真正观察者,所以你应该这样声明它。

    您的测试中似乎根本不需要观察者 - 您只想读取实时数据的值以查看它是否已根据事物的外观更新:

    val characters = charactersLiveData.value
    assertEquals(characters, listOf(Character (
                                name = "myName",
                                img = "image",
                                occupation = arrayListOf(),
                                status = "status",
                                nickname = "nickName",
                                appearance = arrayListOf()
                        )))
    

    此外,在检查相等性时,请确保 Characterdata class 或具有适当的 equals 方法,以便正确检查结构相等性。

    【讨论】:

      猜你喜欢
      • 2019-09-15
      • 2019-04-15
      • 2011-08-08
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多