在 Kotlin 中,我们可以拥有函数对象并作为函数参数传入。
- 如何创建单元测试来测试函数对象逻辑? (例如下面的
funcParam
) 如何对有函数参数的函数进行单元测试? (例如下面的
functionWithFuncParam
) - 即我可以为funcParam
创建一个模拟吗?class MyClass1(val myObject: MyObject) { val funcParam = fun (num: Int): Int { return num * num } fun myFunctionOne() { myObject.functionWithFuncParam(funcParam) } } class MyObject () { fun functionWithFuncParam(funcParam: (Int) -> Int) { println(funcParam(32)) } }
最佳答案
假设 funcParam
有意为 public
,您可以像任何其他方法一样测试它:
class MyClass1Tests {
val sut = MyClass1(MyObject())
@Test
fun `funcParam multiplies input`() {
assertThat(sut.funcParam(4), equalTo(16))
assertThat(sut.funcParam(1), equalTo(1))
assertThat(sut.funcParam(0), equalTo(0))
assertThat(sut.funcParam(-10), equalTo(100))
}
}
如果 funcParam
是私有(private)的,则不应直接测试其行为,而只能通过其包含类的公共(public)接口(interface)进行测试。
测试 functionWithFuncParam
时,您可以轻松提供 (Int) -> Int
的 stub 实现:
class MyObjectTests {
val outContent = ByteArrayOutputStream().apply {
System.setOut(PrintStream(this))
}
val sut = MyObject()
@Test
fun `functionWithFuncParam prints function output `() {
sut.functionWithFuncParam { 12345678 }
assertThat(outContent.toString(), containsString("12345678"))
}
}
如果您想测试 MyClass1
与 MyObject
的交互,一种方法是使用 MyClass1< 中实现的
。如果两个类是不同的协作者,从某种意义上说,他们具有独立的、大部分不相关的行为,通常是最好的选择:MyObject
接口(interface)
interface FunctionalObj {
fun functionWithFuncParam(funcParam: (Int) -> Int)
}
class MyClass1(val myObject: FunctionalObj) {
//omitted for brevity
}
class MyClass1Tests {
var params = mutableListOf<(Int)->Int>()
val sut = MyClass1(object: FunctionalObj {
override fun functionWithFuncParam(funcParam: (Int) -> Int) { params.add(funcParam) }
})
@Test
fun `myFunctionOne calls delegate`() {
sut.myFunctionOne()
assertThat(params.size, equalTo(1))
assertThat(params[0], equalTo(sut.funcParam))//only if `funcParam` is public
}
}
如果 MyClass1
和 MyObject
交互更复杂(即涉及更多调用 queries and commands ),则意味着它们是密切合作的同行。在这种情况下,使用模拟可能会导致测试变得脆弱且难以编写。
关于unit-testing - 函数参数和对象的 Kotlin 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37655431/