【问题标题】:Mockk spky throwing NoClassDefFoundErrorMockk spky 抛出 NoClassDefFoundError
【发布时间】:2021-05-28 09:55:36
【问题描述】:

我正在尝试在 Mockk 的帮助下为我的视图模型编写单元测试。

@Test
fun `When loading the ResponseViewState isLoading`() {
    val observer = spyk<Observer<ResponseViewState>>(Observer { })
    puppiesViewModel.status_.observeForever(observer)

    every {
        fetchPuppiesUseCase.fetchPuppies()
    } returns
            Observable.just(Resource.Loading)

    puppiesViewModel.fetchPuppies()

    val slot = slot<ResponseViewState>()
    verify { observer.onChanged(capture(slot)) }

    assert(slot.captured.isLoading())

    verify { fetchPuppiesUseCase.fetchPuppies() }
}

当我通过 spyk 创建观察者时发生错误。

val observer = spyk<Observer<ResponseViewState>>(Observer { })

我得到的错误是

java.lang.NoClassDefFoundError: com/example/tink/PuppiesViewModelTest$$Lambda$61/0x0000000800176840

    at jdk.internal.reflect.GeneratedSerializationConstructorAccessor4.newInstance(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at io.mockk.proxy.jvm.ObjenesisInstantiator.instanceViaObjenesis(ObjenesisInstantiator.kt:75)
    at io.mockk.proxy.jvm.ObjenesisInstantiator.instance(ObjenesisInstantiator.kt:42)
    at io.mockk.proxy.jvm.ProxyMaker.instantiate(ProxyMaker.kt:75)
    at io.mockk.proxy.jvm.ProxyMaker.proxy(ProxyMaker.kt:42)
    at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:34)
    at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:29)
    at io.mockk.impl.instantiation.AbstractMockFactory.spyk(AbstractMockFactory.kt:102)
    at com.example.tink.PuppiesViewModelTest.createObserver(PuppiesViewModelTest.kt:99)
    at com.example.tink.PuppiesViewModelTest.given loading state, when fetchPuppies called, then isLoading return true(PuppiesViewModelTest.kt:40)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
Caused by: java.lang.ClassNotFoundException: com.example.tink.PuppiesViewModelTest$$Lambda$61.0x0000000800176840

知道如何修复甚至更好的测试方法吗?

【问题讨论】:

  • 面临同样的错误.. 有人知道吗?

标签: android junit mockito mockk


【解决方案1】:

似乎该更改与 Kotlin 相关,并且是在 1.5 版中进行的。 更改 KT-44912 与 Kotlin 编译器如何生成实现 SAM 接口的匿名类有关。

您可以通过将 Kotlin 版本更改为 1.4.32(最新 1.4.X)来轻松测试。

一个简单的解决方案是将您的代码更改为以下内容:

 val observer = createMockObserver()
@Suppress("ObjectLiteralToLambda")
fun createMockObserver(): Observer<ResponseViewState> {
    val observer = object : Observer<ResponseViewState> {

        override fun onChanged(t: ResponseViewState?) { }
    }

    return spyk<Observer<ResponseViewState>>(observer)
}

或者,您可以强制 Kotlin 编译器使用 1.5 之前的匿名类生成,方法是将以下内容添加到 build.gradleandroid 块下:

afterEvaluate {
    compileDebugUnitTestKotlin {
        kotlinOptions {
            freeCompilerArgs += [
                    '-Xsam-conversions=class',
            ]
        }
    }
}

【讨论】:

  • 所以预计我们不能在最新的 kotlin 版本上使用这种方式,还是他们将来会修复?
  • 这也是我想知道的,我最近遇到了这个问题,我不知道哪个选项更好,选择抑制 ObjectLiteralToLambda 警告或强制 kotlin 编译器回退到 1.5 之前匿名类生成。
猜你喜欢
  • 2021-06-13
  • 1970-01-01
  • 2023-04-08
  • 2019-12-31
  • 2010-12-19
  • 2016-01-08
  • 2012-10-06
  • 2011-08-27
  • 2019-09-23
相关资源
最近更新 更多