Merge pull request #2787 from ryanhaining/wear_util_test

Updates WearUtil for easier mocking
This commit is contained in:
Milos Kozak 2023-09-16 16:25:47 +02:00 committed by GitHub
commit d374acbde1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 42 deletions

View file

@ -118,6 +118,7 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-datetime:$kotlinx_datetime_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// for old fashioned support-app version
@ -145,4 +146,4 @@ configurations {
all {
exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx'
}
}
}

View file

@ -3,11 +3,13 @@ package info.nightscout.androidaps.di
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.WearApp
import info.nightscout.rx.di.RxModule
import info.nightscout.shared.di.SharedModule
import info.nightscout.shared.impl.di.SharedImplModule
import kotlinx.datetime.Clock
@Suppress("unused")
@Module(
@ -27,5 +29,8 @@ open class WearModule {
@Binds fun bindContext(aaps: WearApp): Context
@Binds fun bindInjector(aaps: WearApp): HasAndroidInjector
}
@Provides
fun providesClock(): Clock = Clock.System
}

View file

@ -5,9 +5,9 @@ import android.os.PowerManager
import info.nightscout.annotations.OpenForTesting
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.datetime.Clock
/**
* Created by andy on 3/5/19.
@ -16,25 +16,26 @@ import javax.inject.Singleton
@Singleton
@OpenForTesting
open class WearUtil @Inject constructor(
open val context: Context,
open val aapsLogger: AAPSLogger
private val context: Context,
private val aapsLogger: AAPSLogger,
private val clock: Clock,
) {
private val debugWakelocks = false
open val rateLimits: MutableMap<String, Long> = HashMap()
private val rateLimits: MutableMap<String, Long> = HashMap()
//==============================================================================================
// Time related util methods
//==============================================================================================
open fun timestamp(): Long {
return System.currentTimeMillis()
return clock.now().toEpochMilliseconds()
}
fun msSince(`when`: Long): Long {
open fun msSince(`when`: Long): Long {
return timestamp() - `when`
}
fun msTill(`when`: Long): Long {
open fun msTill(`when`: Long): Long {
return `when` - timestamp()
}

View file

@ -6,44 +6,32 @@ import info.nightscout.androidaps.interaction.utils.Constants
import info.nightscout.androidaps.interaction.utils.Persistence
import info.nightscout.androidaps.interaction.utils.WearUtil
import info.nightscout.androidaps.testing.mocks.SharedPreferencesMock
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil
import info.nightscout.sharedtests.TestBase
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import org.junit.jupiter.api.BeforeEach
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
class FakeWearUtil(context: Context, aapsLogger: AAPSLogger) : WearUtil(context, aapsLogger) {
private var clockMsDiff = 0L
override fun timestamp(): Long = REF_NOW + clockMsDiff
fun progressClock(byMilliseconds: Long) {
clockMsDiff += byMilliseconds
}
companion object {
const val REF_NOW = 1572610530000L
}
}
open class WearTestBase : TestBase() {
private var clockNow: Long = REF_NOW
@Mock lateinit var context: Context
@Mock lateinit var sp: SP
@Mock lateinit var dateUtil: DateUtil
lateinit var fakeWearUtil: FakeWearUtil
@Mock lateinit var clock: Clock
lateinit var wearUtil: WearUtil
lateinit var persistence: Persistence
private val mockedSharedPrefs: HashMap<String, SharedPreferences> = HashMap()
@BeforeEach
fun setup() {
fakeWearUtil = FakeWearUtil(context, aapsLogger)
wearUtil = WearUtil(context, aapsLogger, clock)
Mockito.doAnswer { invocation ->
val key = invocation.getArgument<String>(0)
if (mockedSharedPrefs.containsKey(key)) {
@ -54,12 +42,25 @@ open class WearTestBase : TestBase() {
return@doAnswer newPrefs
}
}.`when`(context).getSharedPreferences(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())
setClockNow()
persistence = Mockito.spy(Persistence(aapsLogger, dateUtil, sp))
}
fun progressClock(byMilliseconds: Long) {
clockNow += byMilliseconds
setClockNow()
}
private fun setClockNow() {
Mockito.`when`(clock.now()).thenReturn(Instant.fromEpochMilliseconds(clockNow))
}
companion object {
const val REF_NOW = 1572610530000L
fun backInTime(d: Int, h: Int, m: Int, s: Int): Long =
FakeWearUtil.REF_NOW - (Constants.DAY_IN_MS * d + Constants.HOUR_IN_MS * h + Constants.MINUTE_IN_MS * m + Constants.SECOND_IN_MS * s)
REF_NOW - (Constants.DAY_IN_MS * d + Constants.HOUR_IN_MS * h + Constants.MINUTE_IN_MS * m + Constants.SECOND_IN_MS * s)
}
}

View file

@ -22,7 +22,7 @@ class DisplayFormatTest : WearTestBase() {
fun mock() {
rawDataMocker = RawDataMocker()
displayFormat = DisplayFormat()
displayFormat.wearUtil = fakeWearUtil
displayFormat.wearUtil = wearUtil
displayFormat.sp = sp
displayFormat.context = context
Mockito.`when`(sp.getBoolean("complication_unicode", true)).thenReturn(true)

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.interaction.utils
import com.google.common.truth.Truth.assertThat
import info.nightscout.androidaps.FakeWearUtil
import info.nightscout.androidaps.WearTestBase
import org.junit.jupiter.api.Test
@ -14,13 +13,13 @@ class WearUtilTest : WearTestBase() {
@Test fun timestampAndTimeDiffsTest() {
// smoke for mocks - since we freeze "now" to get stable tests
assertThat(fakeWearUtil.timestamp()).isEqualTo(FakeWearUtil.REF_NOW)
assertThat(fakeWearUtil.msTill(FakeWearUtil.REF_NOW)).isEqualTo(0L)
assertThat(fakeWearUtil.msTill(FakeWearUtil.REF_NOW + 3456L)).isEqualTo(3456L)
assertThat(fakeWearUtil.msTill(FakeWearUtil.REF_NOW - 6294L)).isEqualTo(-6294L)
assertThat(fakeWearUtil.msTill(FakeWearUtil.REF_NOW)).isEqualTo(0L)
assertThat(fakeWearUtil.msSince(FakeWearUtil.REF_NOW + 3456L)).isEqualTo(-3456L)
assertThat(fakeWearUtil.msSince(FakeWearUtil.REF_NOW - 6294L)).isEqualTo(6294L)
assertThat(wearUtil.timestamp()).isEqualTo(REF_NOW)
assertThat(wearUtil.msTill(REF_NOW)).isEqualTo(0L)
assertThat(wearUtil.msTill(REF_NOW + 3456L)).isEqualTo(3456L)
assertThat(wearUtil.msTill(REF_NOW - 6294L)).isEqualTo(-6294L)
assertThat(wearUtil.msTill(REF_NOW)).isEqualTo(0L)
assertThat(wearUtil.msSince(REF_NOW + 3456L)).isEqualTo(-3456L)
assertThat(wearUtil.msSince(REF_NOW - 6294L)).isEqualTo(6294L)
}
@Test fun joinSetTest() {
@ -99,12 +98,12 @@ class WearUtilTest : WearTestBase() {
*/
@Test fun rateLimitTest() {
// WHEN
val firstCall = fakeWearUtil.isBelowRateLimit("test-limit", 3)
val callAfterward = fakeWearUtil.isBelowRateLimit("test-limit", 3)
fakeWearUtil.progressClock(500L)
val callTooSoon = fakeWearUtil.isBelowRateLimit("test-limit", 3)
fakeWearUtil.progressClock(3100L)
val callAfterRateLimit = fakeWearUtil.isBelowRateLimit("test-limit", 3)
val firstCall = wearUtil.isBelowRateLimit("test-limit", 3)
val callAfterward = wearUtil.isBelowRateLimit("test-limit", 3)
progressClock(500L)
val callTooSoon = wearUtil.isBelowRateLimit("test-limit", 3)
progressClock(3100L)
val callAfterRateLimit = wearUtil.isBelowRateLimit("test-limit", 3)
// THEN
assertThat(firstCall).isTrue()