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

View file

@ -3,11 +3,13 @@ package info.nightscout.androidaps.di
import android.content.Context import android.content.Context
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.WearApp import info.nightscout.androidaps.WearApp
import info.nightscout.rx.di.RxModule import info.nightscout.rx.di.RxModule
import info.nightscout.shared.di.SharedModule import info.nightscout.shared.di.SharedModule
import info.nightscout.shared.impl.di.SharedImplModule import info.nightscout.shared.impl.di.SharedImplModule
import kotlinx.datetime.Clock
@Suppress("unused") @Suppress("unused")
@Module( @Module(
@ -27,5 +29,8 @@ open class WearModule {
@Binds fun bindContext(aaps: WearApp): Context @Binds fun bindContext(aaps: WearApp): Context
@Binds fun bindInjector(aaps: WearApp): HasAndroidInjector @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.annotations.OpenForTesting
import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlinx.datetime.Clock
/** /**
* Created by andy on 3/5/19. * Created by andy on 3/5/19.
@ -16,25 +16,26 @@ import javax.inject.Singleton
@Singleton @Singleton
@OpenForTesting @OpenForTesting
open class WearUtil @Inject constructor( open class WearUtil @Inject constructor(
open val context: Context, private val context: Context,
open val aapsLogger: AAPSLogger private val aapsLogger: AAPSLogger,
private val clock: Clock,
) { ) {
private val debugWakelocks = false private val debugWakelocks = false
open val rateLimits: MutableMap<String, Long> = HashMap() private val rateLimits: MutableMap<String, Long> = HashMap()
//============================================================================================== //==============================================================================================
// Time related util methods // Time related util methods
//============================================================================================== //==============================================================================================
open fun timestamp(): Long { 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` return timestamp() - `when`
} }
fun msTill(`when`: Long): Long { open fun msTill(`when`: Long): Long {
return `when` - timestamp() 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.Persistence
import info.nightscout.androidaps.interaction.utils.WearUtil import info.nightscout.androidaps.interaction.utils.WearUtil
import info.nightscout.androidaps.testing.mocks.SharedPreferencesMock import info.nightscout.androidaps.testing.mocks.SharedPreferencesMock
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil import info.nightscout.shared.utils.DateUtil
import info.nightscout.sharedtests.TestBase import info.nightscout.sharedtests.TestBase
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito 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() { open class WearTestBase : TestBase() {
private var clockNow: Long = REF_NOW
@Mock lateinit var context: Context @Mock lateinit var context: Context
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var dateUtil: DateUtil @Mock lateinit var dateUtil: DateUtil
lateinit var fakeWearUtil: FakeWearUtil @Mock lateinit var clock: Clock
lateinit var wearUtil: WearUtil
lateinit var persistence: Persistence lateinit var persistence: Persistence
private val mockedSharedPrefs: HashMap<String, SharedPreferences> = HashMap() private val mockedSharedPrefs: HashMap<String, SharedPreferences> = HashMap()
@BeforeEach @BeforeEach
fun setup() { fun setup() {
fakeWearUtil = FakeWearUtil(context, aapsLogger) wearUtil = WearUtil(context, aapsLogger, clock)
Mockito.doAnswer { invocation -> Mockito.doAnswer { invocation ->
val key = invocation.getArgument<String>(0) val key = invocation.getArgument<String>(0)
if (mockedSharedPrefs.containsKey(key)) { if (mockedSharedPrefs.containsKey(key)) {
@ -54,12 +42,25 @@ open class WearTestBase : TestBase() {
return@doAnswer newPrefs return@doAnswer newPrefs
} }
}.`when`(context).getSharedPreferences(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()) }.`when`(context).getSharedPreferences(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())
setClockNow()
persistence = Mockito.spy(Persistence(aapsLogger, dateUtil, sp)) 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 { companion object {
const val REF_NOW = 1572610530000L
fun backInTime(d: Int, h: Int, m: Int, s: Int): Long = 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() { fun mock() {
rawDataMocker = RawDataMocker() rawDataMocker = RawDataMocker()
displayFormat = DisplayFormat() displayFormat = DisplayFormat()
displayFormat.wearUtil = fakeWearUtil displayFormat.wearUtil = wearUtil
displayFormat.sp = sp displayFormat.sp = sp
displayFormat.context = context displayFormat.context = context
Mockito.`when`(sp.getBoolean("complication_unicode", true)).thenReturn(true) Mockito.`when`(sp.getBoolean("complication_unicode", true)).thenReturn(true)

View file

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