【问题标题】:Parameter specified as non-null is null when using Mokito anyObject() on Kotlin function在 Kotlin 函数上使用 Mokito anyObject() 时,指定为非 null 的参数为 null
【发布时间】:2016-05-21 06:28:25
【问题描述】:

我的代码如下,参考https://stackoverflow.com/a/30308199/3286489中的解决方案

import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.*

class SimpleClassTest {

    private fun <T> anyObject(): T {
        Mockito.anyObject<T>()
        return uninitialized()
    }

    private fun <T> uninitialized(): T = null as T
    lateinit var simpleObject: SimpleClass
    @Mock lateinit var injectedObject: InjectedClass


    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    @Test
    fun testSimpleFunction() {
        simpleObject = SimpleClass(injectedObject)

        verify(injectedObject).settingDependentObject(anyObject())

    }
}

我仍然有以下错误

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method my.package.InjectedClass.settingDependentObject, parameter dependentObject

我错过了什么吗?

更新 下面是经过测试的代码(最简单的形式和工作)

class SimpleClass(val injectedClass: InjectedClass) {

    fun simpleFunction() {
        injectedClass.settingDependentObject(DependentClass(Response.Builder().build()))
    }
}

open class DependentClass(response: Response) {

}

open class InjectedClass() {
    lateinit var dependentObject: DependentClass

    fun settingDependentObject(dependentObject: DependentClass) {
        this.dependentObject = dependentObject
    }
}

【问题讨论】:

    标签: mockito kotlin


    【解决方案1】:

    默认情况下 Kotlin classes and members are final。嘲笑cannot mock final classes or methods。 因此,当您编写时:

    verify(injectedObject).settingDependentObject(anyObject())
    

    调用真正的实现,它需要非空参数。

    要解决此问题,请打开您的类和方法,或者更好的是,更改SimpleClass 以接受接口作为其构造函数参数并改为模拟接口。

    【讨论】:

    • 我的 injectObject 类已经是一个开放类。 settingDependentObject 需要一个非空对象,但 anyObject() 返回空。这就是为什么我认为stackoverflow.com/a/30308199/3286489 中的解决方案将帮助我克服 null 所需的问题。但它仍然无法正常工作。
    • @Elye 请将InjectedClass 来源添加到问题中
    • 将要测试的类添加到上面的更新中。谢谢!
    • @Elye 你需要打开类和方法才能让 Mockito 工作
    • 是的,打开 settingDependentObject,让事情变得更好。谢谢!
    【解决方案2】:

    在使用 Mockito 进行单元测试时,有一个专门帮助处理 Kotlin“默认关闭”的项目。对于 JUNIT,您可以使用kotlin-testrunner,这是一种让任何 Kotlin 测试在类加载器加载类时自动打开类进行测试的简单方法。用法很简单,只需添加@RunWith(KotlinTestRunner::class)的注解即可,例如:

    @RunWith(KotlinTestRunner::class)
    class MyKotlinTestclass {
       @Test 
       fun test() {
       ...
       }
    }
    

    这在文章Never say final: mocking Kotlin classes in unit tests中有详细介绍

    这通过允许模拟所有原本不允许的类以自动方式涵盖您的用例。

    【讨论】:

      【解决方案3】:

      我在使用 RETURNS_DEEP_STUBS 时遇到了与 Mockito 相同的问题。即使使用 kotlin-allopen 插件,嵌套对象似乎仍然返回空值。

      如果您遇到同样的问题,请在 Mockito 上查看并评论 this issue

      【讨论】:

        【解决方案4】:

        你可以用这个函数代替

        inline fun <reified T : Any> any(): T = Mockito.any(T::class.java) ?: T::class.java.newInstance()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-26
          • 1970-01-01
          • 2019-04-15
          • 1970-01-01
          • 2022-01-19
          • 2023-03-29
          • 1970-01-01
          相关资源
          最近更新 更多