Android Kotlin单元测试因io.mockk.MockKException失败:未找到答案

艾萨克爵士

编辑:为将来的读者。我不知道这个问题是否会对您有很大帮助。有趣的逻辑已经发生了很大变化,因此我将关闭该问题,但不会删除。

我正在尝试为ViewModel编写一些单元测试。我正在使用Mockk和Junit5。

应该发生的情况:模拟的存储库返回了falseresponse,我在VM中称其为fun,它将livedata设置为false响应数据。

实际发生的情况:

Exception in thread "DefaultDispatcher-worker-2 @coroutine#1" io.mockk.MockKException: no answer found for: DrillRepository(#1).loadDrillTypes()
    at io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:90)
    at io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
    at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
    at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
    at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:25)
    at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:20)
    at com.nikolam.basketpro.data.DrillRepository.loadDrillTypes(DrillRepository.kt:11)
    at com.nikolam.basketpro.ui.drills.selection.DrillsSelectionViewModel$fetchDrillTypes$1.invokeSuspend(DrillsSelectionViewModel.kt:41)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)

org.opentest4j.AssertionFailedError: 
Expected :[DrillsType(drillType_title=title1, drillType_imageUrl=url1), DrillsType(drillType_title=title2, drillType_imageUrl=url2)]
Actual   :null
<Click to see difference>


    at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
    at org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1124)
    at com.nikolam.basketpro.ui.drills.selection.DrillsSelectionViewModelTest.drillTypeListWillBePopulatedOnSuccess(DrillsSelectionViewModelTest.kt:43)
    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.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:205)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:201)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

这是测试

@ExtendWith(value = [InstantExecutorExtension::class, TestSchedulerExtension::class])
internal class DrillsSelectionViewModelTest{

    val mockkDrillRepository = mockk<DrillRepository>()

    lateinit var drillsSelectionViewModel : DrillsSelectionViewModel

    @BeforeEach
    fun setup(){

        drillsSelectionViewModel = DrillsSelectionViewModel(mockkDrillRepository)

        val fakeResponse = Observable.just(DrillsType("title1", "url1"), DrillsType("title2","url2"))


        every{ mockkDrillRepository.loadDrillTypes()} returns fakeResponse

    }

    @Test
    fun `should update the livedata with correct data from the repository`(){

        drillsSelectionViewModel.fetchDrillTypes()

        assertEquals(arrayListOf(DrillsType("title1", "url1"), DrillsType("title2","url2")), getValue(drillsSelectionViewModel.drillsTypeList.value))

    }

}

这是测试中扩展的两个类

class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {

    override fun beforeEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
            override fun executeOnDiskIO(runnable: Runnable) {
                runnable.run()
            }

            override fun postToMainThread(runnable: Runnable) {
                runnable.run()
            }

            override fun isMainThread(): Boolean {
                return true
            }
        })
    }

    override fun afterEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(null)
    }

}
class TestSchedulerExtension : BeforeTestExecutionCallback, AfterTestExecutionCallback {

    override fun beforeTestExecution(context: ExtensionContext?) {
        RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
        RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
    }

    override fun afterTestExecution(context: ExtensionContext?) {
        RxJavaPlugins.reset()
        RxAndroidPlugins.reset()
    }

}

这是SUT

class DrillsSelectionViewModel(private val repository: DrillRepository): ViewModel() {

    private val compositeDisposable = CompositeDisposable()

    private var _drillsTypeList = MutableLiveData<ArrayList<DrillsType>>()
    val drillsTypeList: LiveData<ArrayList<DrillsType>>
        get() = _drillsTypeList


    init{

        fetchDrillTypes()
    }

    fun fetchDrillTypes()
    {

        val list = ArrayList<DrillsType>()

        viewModelScope.launch(Dispatchers.IO) {
            compositeDisposable += repository.loadDrillTypes()
                .subscribeWith(object : DisposableObserver<DrillsType>() {

                    override fun onError(e: Throwable) {
                        Log.d("TAG", e?.message)
                    }

                    override fun onNext(data: DrillsType) {
                        Log.d("TAG", "data is " + data.toString())
                        list.add(data)
                    }

                    override fun onComplete() {
                        Log.d("TAG", "COMPLETE")
                        _drillsTypeList.postValue(list)
                    }
                })
        }
    }


    override fun onCleared() {
        super.onCleared()
        if (!compositeDisposable.isDisposed) {
            compositeDisposable.dispose()
        }
    }

}

DOC



    fun loadDrillTypes(): Observable<DrillsType> {
        return remoteDataSource.loadDrillTypes()
    }


    fun loadDrillList(drillType : String): Observable<Drill> {
        return remoteDataSource.loadDrillList(drillType)
    }
}

我试过的

  1. 从混合物中取出协程。我认为删除“ viewmodelscope.launch”将使测试工作正常,因为我认为它与协程有关,并且它们没有完成,或者没有及时完成,或者没有在适当的线程上侦听。

  2. 使用下面发布的2个扩展类进行了尝试(以替换JUnit4中的即时执行规则)

  3. 大量搜索以发现类似问题...

很长的帖子很抱歉,您需要随时询问更多信息或代码,如果可能的话还指出一些可以做得更好的错误/事情。任何带有解释的答案都非常感谢。我真的很想了解潜在的问题。非常感谢你!

编辑:我正在考虑这可能是由于RXKotlin

罗斯·沃尔夫

在您的setup()方法中,您首先要创建一个视图模型,然后再在存储库中配置模拟响应。但是,您的viewmodel会尝试在实例化时立即从存储库中获取该响应(在实例中fetchDrillTypes()调用该响应init),因此它会在模拟就绪之前发生。您只需要对呼叫进行重新排序,setup()以便drillsSelectionViewModel = ...最后进行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Android 本地单元测试 - 使用 MockK 模拟 FirebaseAuth

来自分类Dev

Kotlin类的Android单元测试因“找不到符号类...”而失败

来自分类Dev

Kotlin类的Android单元测试因“找不到符号类...”而失败

来自分类Dev

io.mockk.MockKException:找不到以下内容的答案:SavedStateHandle(#1).set(Key,Something)

来自分类Dev

Android使用MockK测试视图模型

来自分类Dev

MockK:未找到答案,因为模拟是从外部修改的

来自分类Dev

尝试验证println或使用Mockk登录kotlin和android

来自分类Dev

Kotlin协程单元测试因“主调度程序的模块初始化失败”而失败

来自分类Dev

Android单元测试改造失败

来自分类Dev

Kotlin junit MockK跑步者

来自分类Dev

Laravel单元测试因自定义属性而失败

来自分类Dev

Android单元测试未报告失败(失败)

来自分类Dev

单元测试因GrailsConfigurationException失败-无法找到负责任的代码行

来自分类Dev

Android Studio“未找到测试”

来自分类Dev

Android Studio“未找到测试”

来自分类Dev

Android单元测试

来自分类Dev

Android单元测试

来自分类Dev

未找到单元测试的值

来自分类Dev

Android检测的测试未找到测试

来自分类Dev

单元测试失败

来自分类Dev

如何使用 Mockk 模拟 android 房间 withTransaction 方法

来自分类Dev

Google Push-To-Deploy管道-单元测试因模块导入错误而失败

来自分类Dev

具有外部依赖关系的Jasmine单元测试指令因TypeError:'[object Object]'而失败

来自分类Dev

单元测试因Observable.FromAsync和Observable.Switch失败

来自分类Dev

Angular2服务单元测试因TypeError失败:undefined不是对象

来自分类Dev

Android单元测试缓存

来自分类Dev

Android中的单元测试?

来自分类Dev

Android单元测试spannablestringbuilder

来自分类Dev

Android中的单元测试?

Related 相关文章

  1. 1

    Android 本地单元测试 - 使用 MockK 模拟 FirebaseAuth

  2. 2

    Kotlin类的Android单元测试因“找不到符号类...”而失败

  3. 3

    Kotlin类的Android单元测试因“找不到符号类...”而失败

  4. 4

    io.mockk.MockKException:找不到以下内容的答案:SavedStateHandle(#1).set(Key,Something)

  5. 5

    Android使用MockK测试视图模型

  6. 6

    MockK:未找到答案,因为模拟是从外部修改的

  7. 7

    尝试验证println或使用Mockk登录kotlin和android

  8. 8

    Kotlin协程单元测试因“主调度程序的模块初始化失败”而失败

  9. 9

    Android单元测试改造失败

  10. 10

    Kotlin junit MockK跑步者

  11. 11

    Laravel单元测试因自定义属性而失败

  12. 12

    Android单元测试未报告失败(失败)

  13. 13

    单元测试因GrailsConfigurationException失败-无法找到负责任的代码行

  14. 14

    Android Studio“未找到测试”

  15. 15

    Android Studio“未找到测试”

  16. 16

    Android单元测试

  17. 17

    Android单元测试

  18. 18

    未找到单元测试的值

  19. 19

    Android检测的测试未找到测试

  20. 20

    单元测试失败

  21. 21

    如何使用 Mockk 模拟 android 房间 withTransaction 方法

  22. 22

    Google Push-To-Deploy管道-单元测试因模块导入错误而失败

  23. 23

    具有外部依赖关系的Jasmine单元测试指令因TypeError:'[object Object]'而失败

  24. 24

    单元测试因Observable.FromAsync和Observable.Switch失败

  25. 25

    Angular2服务单元测试因TypeError失败:undefined不是对象

  26. 26

    Android单元测试缓存

  27. 27

    Android中的单元测试?

  28. 28

    Android单元测试spannablestringbuilder

  29. 29

    Android中的单元测试?

热门标签

归档