I would like to test the lambda function that is passed to the getObject call, by passing my own Get...
t
I would like to test the lambda function that is passed to the getObject call, by passing my own GetObjectResponse object, so all the logic implemented inside the lambda is tested, including the calls to produceFlow and consumeFlow private funs How I could mock something like this? Any idea/advice?
c
Not with S3, but equivalent on CloudWatch logs.
Copy code
val cwLogsClient = mockk<CloudWatchLogsClient>(relaxed = true)
        val putLogEventsRequestSlot = slot<PutLogEventsRequest>()
        every {
            cwLogsClient.putLogEvents(capture(putLogEventsRequestSlot))
        } answers {
            PutLogEventsResponse.builder()
                .nextSequenceToken(sequenceToken)
                .build()
        }
t
Thanks for the response @Chris Lee.... I've tried a couple of different things with no luck. One of the differences I see in you sample and my use case is that in my case, the testing function receives a LAMBDA that receives the object I wanna mock. I know I'm doing something terrible wrong, thanks again for the help
Copy code
coEvery {
    val getObjectResponseSlot = slot<GetObjectResponse>()
    // s3Client.getObject(any<GetObjectRequest>(),    any<suspend (GetObjectResponse) -> Unit>()) // this compiles
    s3Client.getObject(any<GetObjectRequest>(),    any<suspend (capture(getObjectResponseSlot)) -> Unit>()) // this does not compile
} answers  {
    GetObjectResponse {
        eTag = "e4f682d7-eb9b-4a7c-9348-84a2704e3f86"
    }
}
Thanks in advance for your help.
o
Sure, this is a hacky solution, but what you could do is create a class like this one:
Copy code
class TestableLambda : (GetObjectResponse) -> String {
	override fun invoke(p1: GetObjectResponse): String {
		TODO()
	}
}
and add a unit test for this lambda class alone. Then rewrite your additional code to use the
TestableLambda
class instead of actually producing the lambda yourself when testing the
read
method, while only verifying that an expected instance (using
refEq
verify clause) is passed to the
getObject
method. I have not thought of any better solution.
t
thank you both @Chris Lee and @Ondřej Šimon this was tested by this TestableLambda approach. It does not look that bad in my opinion... I always had had a bad feeling about lambdas and UnitTesting, so creating a class to implement all this logic is ok to me.
o
The thing is, and it is not as apparent when using lambda, is that specifying lambda basically creates an object on the spot within your execution, in the same manner as calling a constructor of a class, which quite often also produces difficult to test code. Thus one needs to think a little bit different when using the lambda approach.
198 Views