Kotlin功能参数和对象的单元测试 [英] Kotlin Unit Testing for Function Parameter and Object
问题描述
在Kotlin中,我们可以具有函数对象并作为函数参数传递.
In Kotlin,, we could have function object and pass in as function parameter.
- 如何创建单元测试来测试功能对象的逻辑? (例如下面的
funcParam
) -
如何对具有功能参数的功能进行单元测试? (例如下面的
functionWithFuncParam
)-即我可以为funcParam
创建一个模拟文件吗?
- How to create unit test to test the function object logic? (e.g.
funcParam
below) How to unit test the function that has function parameter? (e.g.
functionWithFuncParam
below) - i.e. can I create a Mock forfuncParam
?
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
,则可以有意地将其测试为任何其他方法:
Assuming funcParam
is public
intentionally you can test it as any other method:
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
是私有的,则不应直接测试其行为,而只能通过其包含类的公共接口进行测试.
If funcParam
is private you shouldn't test its behavior directly but only through public interface of it's containing class.
在测试functionWithFuncParam
时,您可以轻松提供(Int) -> Int
的存根实现:
When testing functionWithFuncParam
you can easily supply a stub implementation of (Int) -> Int
:
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"))
}
}
如果您想测试与MyObject
的MyClass1
交互,一种方法是使用MyClass1
中由MyObject
实现的接口.通常,如果2个类是截然不同的协作者,则最好的选择是从某种意义上说,它们具有独立的,几乎不相关的行为:
If you'd like to test MyClass1
interaction with MyObject
one way is to use interface implemented MyObject
by in MyClass1
. Usually the best choice if 2 classes are distinct collaborators in a sense that they have separate mostly unrelated behaviour:
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
的交互更为复杂(即涉及更多调用,则
If MyClass1
and MyObject
interaction is more complex (i.e. involves more calls both queries and commands) it would imply that they are peers working together closely. In such case, using mocks can lead to brittle and hard to write tests.
这篇关于Kotlin功能参数和对象的单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!