Uses injected clock rather than System for time

This is better for mocking
This commit is contained in:
Ryan Haining 2023-09-15 08:34:47 -07:00
parent 1bed0251d2
commit 86b259e244
4 changed files with 37 additions and 35 deletions

View file

@ -7,6 +7,7 @@ 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.
@ -17,6 +18,7 @@ import javax.inject.Singleton
open class WearUtil @Inject constructor( open class WearUtil @Inject constructor(
private val context: Context, private val context: Context,
private val aapsLogger: AAPSLogger, private val aapsLogger: AAPSLogger,
private val clock: Clock,
) { ) {
private val debugWakelocks = false private val debugWakelocks = false
@ -26,7 +28,7 @@ open class WearUtil @Inject constructor(
// Time related util methods // Time related util methods
//============================================================================================== //==============================================================================================
open fun timestamp(): Long { open fun timestamp(): Long {
return System.currentTimeMillis() return clock.now().toEpochMilliseconds()
} }
open fun msSince(`when`: Long): Long { open fun msSince(`when`: Long): Long {

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()