kotlinmockk

Kotlin mockK chained calls to repository


I am unsure how to mockK chained calls to a repository in kotlin

Assuming I have this service....

@Service
class FooService @Autowired constructor(
    private val denmarkRepository: DenmarkRepository,
    private val swedenRepository: SwedenRepository,
) {
    fun getFoo(id: UUID): List<Currency> {
        val currentDateTime = ZonedDateTime.now()
        val result1 =
            denmarkRepository.findById(id, currentDateTime)?.let { result ->
                countryRepository.findCurrencyWithIdAndTime(
                    result.defaultSelection.id,
                    currentDateTime
                )?.let { currency -> CurrencyDto(...) }
            }

        val result2 =
            swedenRepository.findById(id, currentDateTime)?.let { result ->
                countryRepository.findCurrencyWithIdAndTime(
                    result.defaultSelection.id,
                    currentDateTime
                )?.let { currency -> CurrencyDto(...) }
            }
    }

    return listOf(result1, result2)
}

...and I want to test the function getFoo(), I would have to mockK denmarkRepository.findById(), countryRepository.findCurrencyWithIdAndTime() and swedenRepository.findById().

every { denmarkRepository.findById(any<Long>(), any<ZonedDateTime>()) } returns denmark
every { swedenRepository.findById(any<Long>(), any<ZonedDateTime>()) } returns sweden
every { countryRepository.findCurrencyWithIdAndTime(any<Long>(), any<ZonedDateTime>()) } returns currency

But, the problem is that countryRepository.findCurrencyWithIdAndTime() now always returns the same values, so result1 and result2 will always be the same. However, this return listOf(result1, result2) in real life is a with different values.

How would I mockK chained calls to repositories, so that the test returns different values eventhough its the same function?


Solution

  • You can use returnsMany to return list of expected values

    every { countryRepository.findCurrencyWithIdAndTime(any<Long>(), any<ZonedDateTime>()) } 
       returnsMany listOf(currency1,currency2)
    

    Alternative way is to chain with andThen

    every { countryRepository.findCurrencyWithIdAndTime(any<Long>(), any<ZonedDateTime>()) } 
       returns currency1 andThen currency2