Repository: corona-warn-app/cwa-app-android
File: Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ccl/configuration/update/CclConfigurationUpdaterTest.kt (Kotlin)

Code before:
import testhelpers.BaseTest

@Suppress("MaxLineLength")
internal class CclConfigurationUpdaterTest : BaseTest() {

    @MockK private lateinit var timeStamper: TimeStamper
    @RelaxedMockK private lateinit var cclSettings: CclSettings
    @MockK private lateinit var boosterRulesRepository: BoosterRulesRepository
    @MockK private lateinit var cclConfigurationRepository: CclConfigurationRepository
    @RelaxedMockK private lateinit var dccWalletInfoUpdateTrigger: DccWalletInfoUpdateTrigger
    @MockK private lateinit var dccValidationRepository: DccValidationRepository

    @BeforeEach
    fun setup() {
        MockKAnnotations.init(this)
        coEvery { cclSettings.forceCclCalculation() } returns false
    }

    @Test
    fun `updateIfRequired() should update booster rules and ccl configuration if required`() = runBlockingTest {
        coEvery { cclSettings.getLastExecutionTime() } returns Instant.parse("2000-01-01T00:00:00Z")
        coEvery { timeStamper.nowUTC } returns Instant.parse("2000-01-02T00:00:00Z")

        coEvery { boosterRulesRepository.update() } returns UpdateResult.UPDATE
        coEvery { cclConfigurationRepository.updateCclConfiguration() } returns UpdateResult.NO_UPDATE
        coEvery { dccValidationRepository.updateInvalidationRules() } returns UpdateResult.NO_UPDATE

        getInstance().updateIfRequired()

        coVerify(exactly = 1) {
            boosterRulesRepository.update()
            cclConfigurationRepository.updateCclConfiguration()
            dccValidationRepository.updateInvalidationRules()

            cclSettings.setExecutionTimeToNow(any())
            dccWalletInfoUpdateTrigger.triggerAfterConfigChange(true)
        }

        // false should be passed to the trigger when there are no updates
        coEvery { boosterRulesRepository.update() } returns UpdateResult.NO_UPDATE
        getInstance().updateIfRequired()
        coVerify(exactly = 1) { dccWalletInfoUpdateTrigger.triggerAfterConfigChange(false) }
    }

    @Test
    fun `updateIfRequired() should NOT update booster rules and ccl configuration if NOT required but should trigger DccWalletInfo recalculation`() =
        runBlockingTest {
            coEvery { cclSettings.getLastExecutionTime() } returns Instant.parse("2000-01-01T00:00:00Z")
            coEvery { timeStamper.nowUTC } returns Instant.parse("2000-01-01T00:00:00Z")

            getInstance().updateIfRequired()

Review comment (suggestion):
I think the function names in this Test Class should now also in include ` ... and invalidation rules...`. Currently, they are something like `updateIfRequired() should update booster rules and ccl configuration if required`()`

Code after:
import testhelpers.BaseTest

@Suppress("MaxLineLength")
internal class CclConfigurationUpdaterTest : BaseTest() {

    @MockK private lateinit var timeStamper: TimeStamper
    @RelaxedMockK private lateinit var cclSettings: CclSettings
    @MockK private lateinit var boosterRulesRepository: BoosterRulesRepository
    @MockK private lateinit var cclConfigurationRepository: CclConfigurationRepository
    @RelaxedMockK private lateinit var dccWalletInfoUpdateTrigger: DccWalletInfoUpdateTrigger
    @MockK private lateinit var dccValidationRepository: DccValidationRepository

    @BeforeEach
    fun setup() {
        MockKAnnotations.init(this)
        coEvery { cclSettings.forceCclCalculation() } returns false
    }

    @Test
    fun `updateIfRequired() should update booster rules, invalidation rules and ccl configuration if required`() =
        runBlockingTest {
            coEvery { cclSettings.getLastExecutionTime() } returns Instant.parse("2000-01-01T00:00:00Z")
            coEvery { timeStamper.nowUTC } returns Instant.parse("2000-01-02T00:00:00Z")

            coEvery { boosterRulesRepository.update() } returns UpdateResult.UPDATE
            coEvery { cclConfigurationRepository.updateCclConfiguration() } returns UpdateResult.NO_UPDATE
            coEvery { dccValidationRepository.updateInvalidationRules() } returns UpdateResult.NO_UPDATE

            getInstance().updateIfRequired()

            coVerify(exactly = 1) {
                boosterRulesRepository.update()
                cclConfigurationRepository.updateCclConfiguration()
                dccValidationRepository.updateInvalidationRules()

                cclSettings.setExecutionTimeToNow(any())
                dccWalletInfoUpdateTrigger.triggerAfterConfigChange(true)
            }

            // false should be passed to the trigger when there are no updates
            coEvery { boosterRulesRepository.update() } returns UpdateResult.NO_UPDATE
            getInstance().updateIfRequired()
            coVerify(exactly = 1) { dccWalletInfoUpdateTrigger.triggerAfterConfigChange(false) }
        }

    @Test
    fun `updateIfRequired() should NOT update if NOT required but should trigger DccWalletInfo recalculation`() =
        runBlockingTest {
            coEvery { cclSettings.getLastExecutionTime() } returns Instant.parse("2000-01-01T00:00:00Z")
            coEvery { timeStamper.nowUTC } returns Instant.parse("2000-01-01T00:00:00Z")