16

假设我们有一个这样的类:

class Whatever {
    private var something = false

    fun aMethod(): Int {
        return if( something ) {
            1
        } else {
            0
        }
    }
}

根据文档,看起来我应该能够执行以下操作:

val classUnderTest = spyk(Whatever())

every { classUnderTest getProperty "something" } returns true

assertThat(classUnderTest.aMethod()).isEqualTo(1)

但是我得到了错误:io.mockk.MockKException: Missing calls inside every { ... } block

我正在使用 mockk 1.8.5,kotlin 1.2.51

4

3 回答 3

8

尝试使用答案而不是返回,如下所示:

val mock = spyk(MockCls(), recordPrivateCalls = true)

every { mock.property } answers { fieldValue }
every { mock getProperty "property" } propertyType Int::class answers { fieldValue + 6 }
every { mock setProperty "property" value any<Int>() } propertyType Int::class answers  { fieldValue += value }
every { mock.property = any() } propertyType Int::class answers {
  fieldValue = value + 1
} andThen {
  fieldValue = value - 1
}
于 2018-11-15T12:40:11.573 回答
4

你可以使用这个小扩展

fun Any.mockPrivateFields(vararg mocks: Any): Any {
    mocks.forEach { mock ->
        javaClass.declaredFields
                .filter { it.modifiers.and(Modifier.PRIVATE) > 0 || it.modifiers.and(Modifier.PROTECTED) > 0 }
                .firstOrNull { it.type == mock.javaClass}
                ?.also { it.isAccessible = true }
                ?.set(this, mock)
    }
    return this
}

它设置作为参数传递的相同类型的第一个字段的值,并且可以使用多个参数,例如:

myObject.mockPrivateFields(1, "hi!")

它将模拟找到的第一个 Int 字段和找到的第一个 String 字段。

这仅适用于私有/受保护的字段。

您可以对其进行修改以支持相同类型的多个字段。我没有尝试使用泛型,但我想支持它并不难。

于 2019-03-27T15:29:58.140 回答
0

发生这种情况可能是因为kotlin 编译器没有为您的属性创建 getter/setter 。something

如果您将其修改为如下所示怎么办?

class Whatever {
    private val something
        get() = false

    fun aMethod(): Int {
        return if( something ) {
            1
        } else {
            0
        }
    }
}
于 2021-03-12T10:10:23.030 回答