如何在setter上调用调用? [英] How to call invoking on a setter?
本文介绍了如何在setter上调用调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我要编写一个测试用例,该测试用例要求setter引发异常。
class ClassUnderTest {
fun regularMethod(){ require(false)}
var currentValue: Int = 0
set(_) {
require(false)
}
}
对于常规函数,我可以简单地执行以下操作:
import org.amshove.kluent.*
import org.junit.jupiter.api.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
class Tests {
@Test
fun `debug throwing fun`() {
val f = ClassUnderTest()
invoking { f.regularMethod() } `should throw` IllegalArgumentException::class
}
}
但对于二传手我有点困惑
@Test
fun `debug throwing setter`() {
val f = ClassUnderTest()
//1) doesn't compile: Expected a value of type Any?
invoking { f.currentValue = 0 } `should throw` IllegalArgumentException::class
//2) works, but why? Is this canonical?
invoking { 0.also { f.currentValue = it } } `should throw` IllegalArgumentException::class
//3 compiles but no exception thrown -> test fails
invoking { { f.currentValue = 0 } } `should throw` IllegalArgumentException::class
}
1)是我的直觉方法。显然,设置器没有返回值。为什么不行?我定义了一个被调用的函数,所以我希望它的行为与void方法相同。
2)Android Studio推荐了这一款。为什么现在这样行得通呢?这是推荐的方式吗?
3)我自己的尝试,为什么这个不起作用?
推荐答案
查看invoking
需要什么作为参数:
fun invoking(function: () -> Any?): () -> Any?
它需要一个返回任何内容的函数。
您的lambda包含赋值语句。出于这样或那样的原因,编译器无法确定如果lambda的类型被推断为() -> Unit
,那么它就可以被转换为() -> Any?
。即:
// here the compiler can infer that the lambda is () -> Unit
val x = { f.currentValue = 0 }
// this now works
invoking(x) `should throw` IllegalArgumentException::class
但是,如果您要求编译器尝试将{ f.currentValue = 0 }
设置为() -> Any?
类型,它会突然变成哑巴并且无法执行。我认为这是因为它试图在lambda中找到一个可以转换为Any?
的表达式,但却找到了一条语句。我不知道这是错误还是故意的行为。
这也行得通:
invoking({ f.currentValue = 0 } as () -> Unit) `should throw` IllegalArgumentException::class
有趣的是,IntelliJ说演员阵容是不必要的,但事实并非如此。
总之,您问题中的第二种方法是可行的,因为0.also { ... }
是一个表达式。
第三种方法不起作用,因为虽然{ f.currentValue = 0 }
是一个表达式,但是您传递给invoking
的lambda现在变成了不会抛出的东西。它变成只返回另一个lambda的东西。您可以:
invoking { run { f.currentValue = 0 } } `should throw` IllegalArgumentException::class
或
invoking { { f.currentValue = 0 }.invoke() } `should throw` IllegalArgumentException::class
改为。
顺便说一句,如果invoking
声明如下:
fun <T> invoking(function: () -> T): () -> Any?
那么您的直观方法&就会奏效。使用() -> Any?
可能有的原因。我不是作者,所以我不知道。
这篇关于如何在setter上调用调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文