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))
}
}
If funcParam
is private you shouldn't test its behavior directly but only through public interface of it's containing class.
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"))
}
}
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
}
}
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.