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.