I've got a unit test using Kotest and Mockk:
package application
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.threeten.extra.Days
import software.amazon.awssdk.services.s3.model.PutObjectResponse
import application.TimeFixture.anInstant
import application.contract.ContractIdFixture.aContractId
import application.contract.ContractStatusFixture.aContractStatus
import application.contract.aws.ContractStatusDdbRepository
import application.commons.aws.S3ClientImpl as S3Client
import java.time.Instant
class ContractServiceTest : FunSpec({
test("test") {
// Given
val s3Client = mockk<S3Client>()
val status = mockk<ContractStatusDdbRepository>()
val underTest = ContractService(repository, s3Client)
val contract = aContractStatus()
every { status.getAll() } returns listOf(contract)
every { s3Client.putObject(any(), any()) } returns mockk<PutObjectResponse>()
// When
val res = underTest.exportAllContracts()
// Then
res.total shouldBe 1
val capturedData = mutableListOf<ByteArray>()
verify(exactly = 1) { status.getAll() }
verify(exactly = 2) { s3Client.putObject(any<String>(), any<String>()) }
// ... rest of the test
}
})
And it passes when running individually. But when I run the whole test suite, it keeps failing with a consistent error message "no answer found", sometimes for repository.getAll
call or s3Client.putObject
call:
no answer found for S3ClientImpl(#1).putObject(myBucket, contracts-2023-12-20.csv) among the configured answers: ()
io.mockk.MockKException: no answer found for S3ClientImpl(#1).putObject(myBucket, contracts.csv) among the configured answers: ()
at app//io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:91)
at app//io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
at app//io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
at app//io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
at app//io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:270)
at app//io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:24)
at app//io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:21)
at app//application.commons.aws.S3ClientImpl.putObject(S3Client.kt:15)
As can be seen in the code, I moved everything inside the test method to isolate it from the rest of the test suite. I also use any
matcher to match anything, just in case. But it keeps failing.
Is there something I'm missing with respect to the internal of Mockk and/or Kotest?
Thanks.
I hit similar problem after migration from mockk 1.12 to 1.13.
If individual test execution succeed, then something resets the mocks (MockK#unmockkAll
?) after earch test run.
This javadoc helped me to find solution:
unmockkAll will not be called if the KeepMocks annotation is present
So, adding @MockKExtension.KeepMocks
annotation to the class prevents mocks reset.