mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2025-12-20 07:54:20 +01:00
Make mock test working
This commit is contained in:
@@ -66,12 +66,11 @@ dependencies {
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.lifecycle.service)
|
||||
|
||||
|
||||
testImplementation(libs.junit4)
|
||||
|
||||
testImplementation("io.mockk:mockk:1.13.5")
|
||||
testImplementation(libs.test.mockk)
|
||||
testImplementation(libs.androidx.test.ext)
|
||||
testImplementation(libs.kotlinx.coroutines.test)
|
||||
testImplementation("org.slf4j:slf4j-simple:2.0.5")
|
||||
testImplementation("org.robolectric:robolectric:4.10.3")
|
||||
testImplementation(libs.test.slf4j.simple)
|
||||
testImplementation(libs.test.robolectric)
|
||||
testImplementation(libs.kotlin.junit)
|
||||
}
|
||||
|
||||
@@ -38,17 +38,24 @@ class GlsServer @Inject constructor(
|
||||
private val scope: CoroutineScope
|
||||
) {
|
||||
|
||||
lateinit var server: BleGattServer
|
||||
|
||||
lateinit var glsCharacteristic: BleServerGattCharacteristic
|
||||
lateinit var glsContextCharacteristic: BleServerGattCharacteristic
|
||||
lateinit var racpCharacteristic: BleServerGattCharacteristic
|
||||
lateinit var batteryLevelCharacteristic: BleServerGattCharacteristic
|
||||
|
||||
private var lastRequest = byteArrayOf()
|
||||
|
||||
val YOUNGEST_RECORD = byteArrayOf(0x07, 0x00, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x05, 0x00, 0x00, 0x26, 0xD2.toByte(), 0x11)
|
||||
val OLDEST_RECORD = byteArrayOf(0x07, 0x04, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x11, 0x00, 0x00, 0x82.toByte(), 0xD2.toByte(), 0x11)
|
||||
|
||||
val records = listOf(
|
||||
byteArrayOf(0x07, 0x00, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x05, 0x00, 0x00, 0x26, 0xD2.toByte(), 0x11),
|
||||
YOUNGEST_RECORD,
|
||||
byteArrayOf(0x07, 0x01, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x08, 0x00, 0x00, 0x3D, 0xD2.toByte(), 0x11),
|
||||
byteArrayOf(0x07, 0x02, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x0B, 0x00, 0x00, 0x54, 0xD2.toByte(), 0x11),
|
||||
byteArrayOf(0x07, 0x03, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x0E, 0x00, 0x00, 0x6B, 0xD2.toByte(), 0x11),
|
||||
byteArrayOf(0x07, 0x04, 0x00, 0xDC.toByte(), 0x07, 0x01, 0x01, 0x0C, 0x1E, 0x11, 0x00, 0x00, 0x82.toByte(), 0xD2.toByte(), 0x11)
|
||||
OLDEST_RECORD
|
||||
)
|
||||
|
||||
val racp = byteArrayOf(0x06, 0x00, 0x01, 0x01)
|
||||
@@ -96,7 +103,7 @@ class GlsServer @Inject constructor(
|
||||
listOf(batteryLevelCharacteristic)
|
||||
)
|
||||
|
||||
val server = BleGattServer.create(
|
||||
server = BleGattServer.create(
|
||||
context = context,
|
||||
config = arrayOf(serviceConfig, batteryService),
|
||||
mock = device
|
||||
@@ -112,6 +119,10 @@ class GlsServer @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun stopServer() {
|
||||
server.stopServer()
|
||||
}
|
||||
|
||||
private fun setUpConnection(connection: BluetoothGattServerConnection) {
|
||||
val glsService = connection.services.findService(GLS_SERVICE_UUID)!!
|
||||
glsCharacteristic = glsService.findCharacteristic(GLUCOSE_MEASUREMENT_CHARACTERISTIC)!!
|
||||
@@ -123,27 +134,33 @@ class GlsServer @Inject constructor(
|
||||
|
||||
|
||||
startGlsService(connection)
|
||||
startBatteryService(connection)
|
||||
// startBatteryService(connection)
|
||||
}
|
||||
|
||||
private fun startGlsService(connection: BluetoothGattServerConnection) {
|
||||
racpCharacteristic.value
|
||||
.filter { it.isNotEmpty() }
|
||||
.onEach {
|
||||
if (it.contentEquals(RecordAccessControlPointInputParser.reportNumberOfAllStoredRecords().value)) {
|
||||
sendAll(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
} else if (it.contentEquals(RecordAccessControlPointInputParser.reportLastStoredRecord().value)) {
|
||||
sendLast(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
} else if (it.contentEquals(RecordAccessControlPointInputParser.reportFirstStoredRecord().value)) {
|
||||
sendFirst(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
}
|
||||
}
|
||||
.onEach { lastRequest = it }
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
internal fun continueWithResponse() {
|
||||
sendResponse(lastRequest)
|
||||
}
|
||||
|
||||
private fun sendResponse(request: ByteArray) {
|
||||
if (request.contentEquals(RecordAccessControlPointInputParser.reportNumberOfAllStoredRecords().value)) {
|
||||
sendAll(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
} else if (request.contentEquals(RecordAccessControlPointInputParser.reportLastStoredRecord().value)) {
|
||||
sendLast(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
} else if (request.contentEquals(RecordAccessControlPointInputParser.reportFirstStoredRecord().value)) {
|
||||
sendFirst(glsCharacteristic)
|
||||
racpCharacteristic.setValue(racp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendFirst(characteristics: BleServerGattCharacteristic) {
|
||||
characteristics.setValue(records.first())
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import kotlinx.coroutines.launch
|
||||
import no.nordicsemi.android.analytics.AppAnalytics
|
||||
import no.nordicsemi.android.analytics.Profile
|
||||
import no.nordicsemi.android.analytics.ProfileConnectedEvent
|
||||
import no.nordicsemi.android.common.logger.BlekLoggerAndLauncher
|
||||
import no.nordicsemi.android.common.navigation.NavigationResult
|
||||
import no.nordicsemi.android.common.navigation.Navigator
|
||||
import no.nordicsemi.android.gls.GlsDetailsDestinationId
|
||||
@@ -67,9 +68,6 @@ import no.nordicsemi.android.kotlin.ble.client.main.service.BleGattServices
|
||||
import no.nordicsemi.android.kotlin.ble.core.ServerDevice
|
||||
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState
|
||||
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus
|
||||
import no.nordicsemi.android.common.logger.BlekLogger
|
||||
import no.nordicsemi.android.common.logger.BlekLoggerAndLauncher
|
||||
import no.nordicsemi.android.kotlin.ble.core.ext.toDisplayString
|
||||
import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser
|
||||
import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementContextParser
|
||||
import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementParser
|
||||
@@ -239,7 +237,6 @@ internal class GLSViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun onAccessControlPointDataReceived(data: RecordAccessControlPointData) = viewModelScope.launch {
|
||||
println("AAA: Response code: ${data}")
|
||||
when (data) {
|
||||
is NumberOfRecordsData -> onNumberOfRecordsReceived(data.numberOfRecords)
|
||||
is ResponseData -> when (data.responseCode) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import io.mockk.mockkStatic
|
||||
import io.mockk.spyk
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
@@ -28,19 +27,21 @@ import no.nordicsemi.android.gls.main.view.OnWorkingModeSelected
|
||||
import no.nordicsemi.android.gls.main.viewmodel.GLSViewModel
|
||||
import no.nordicsemi.android.kotlin.ble.client.main.ClientScope
|
||||
import no.nordicsemi.android.kotlin.ble.core.MockServerDevice
|
||||
import no.nordicsemi.android.kotlin.ble.core.ServerDevice
|
||||
import no.nordicsemi.android.kotlin.ble.core.data.BleGattConnectionStatus
|
||||
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState
|
||||
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus
|
||||
import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementParser
|
||||
import no.nordicsemi.android.kotlin.ble.profile.gls.data.RequestStatus
|
||||
import no.nordicsemi.android.kotlin.ble.server.main.ServerScope
|
||||
import no.nordicsemi.android.ui.view.NordicLoggerFactory
|
||||
import no.nordicsemi.android.ui.view.StringConst
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertContentEquals
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
@@ -93,6 +94,7 @@ internal class GLSViewModelTest {
|
||||
every { ClientScope } returns CoroutineScope(UnconfinedTestDispatcher())
|
||||
mockkStatic("no.nordicsemi.android.kotlin.ble.server.main.ServerScopeKt")
|
||||
every { ServerScope } returns CoroutineScope(UnconfinedTestDispatcher())
|
||||
every { stringConst.APP_NAME } returns "Test"
|
||||
|
||||
viewModel = spyk(GLSViewModel(context, navigator, analytics, stringConst, object :
|
||||
NordicLoggerFactory {
|
||||
@@ -106,6 +108,8 @@ internal class GLSViewModelTest {
|
||||
}
|
||||
|
||||
}))
|
||||
justRun { viewModel.logAnalytics(any()) }
|
||||
|
||||
glsServer = GlsServer(CoroutineScope(UnconfinedTestDispatcher()))
|
||||
glsServer.start(spyk(), device)
|
||||
}
|
||||
@@ -123,54 +127,71 @@ internal class GLSViewModelTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkOnClick() = runTest {
|
||||
// every { viewModel.recordAccessControlPointCharacteristic } returns characteristic
|
||||
// coJustRun { characteristic.write(any(), any()) }
|
||||
|
||||
viewModel.onEvent(OnWorkingModeSelected(WorkingMode.FIRST))
|
||||
|
||||
advanceUntilIdle()
|
||||
assertEquals(RequestStatus.PENDING, viewModel.state.value.glsServiceData.requestStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when connection fails return disconnected`() {
|
||||
val serverDevice = mockk<ServerDevice>()
|
||||
fun `when connection fails return disconnected`() = runTest {
|
||||
val disconnectedState = GattConnectionStateWithStatus(
|
||||
GattConnectionState.STATE_DISCONNECTED,
|
||||
BleGattConnectionStatus.SUCCESS
|
||||
)
|
||||
// every { viewModel.recordAccessControlPointCharacteristic } returns characteristic
|
||||
// coJustRun { characteristic.write(any(), any()) }
|
||||
mockkStatic("no.nordicsemi.android.kotlin.ble.client.main.ClientDeviceExtKt")
|
||||
every { serverDevice.name } returns "Test"
|
||||
every { serverDevice.address } returns "11:22:33:44:55"
|
||||
every { stringConst.APP_NAME } returns "Test"
|
||||
viewModel.handleResult(NavigationResult.Success(device))
|
||||
glsServer.stopServer()
|
||||
|
||||
viewModel.handleResult(NavigationResult.Success(serverDevice))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertEquals(disconnectedState, viewModel.state.value.glsServiceData.connectionState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkOnClick2() = runTest {
|
||||
every { stringConst.APP_NAME } returns "Test"
|
||||
justRun { viewModel.logAnalytics(any()) }
|
||||
|
||||
fun `when request first record then change status and get 1 record`() = runTest {
|
||||
viewModel.handleResult(NavigationResult.Success(device))
|
||||
advanceUntilIdle() //Needed because of delay() in waitForBonding()
|
||||
assertEquals(RequestStatus.IDLE, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
advanceUntilIdle()
|
||||
delay(1000)
|
||||
viewModel.onEvent(OnWorkingModeSelected(WorkingMode.FIRST))
|
||||
assertEquals(RequestStatus.PENDING, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
// advanceUntilIdle()
|
||||
// assertEquals(RequestStatus.PENDING, viewModel.state.value.glsServiceData.requestStatus)
|
||||
//
|
||||
//// glsServer.glsCharacteristic.setValue(glsServer.records.first())
|
||||
// glsServer.racpCharacteristic.setValue(glsServer.racp)
|
||||
//
|
||||
// advanceUntilIdle()
|
||||
//
|
||||
// assertEquals(RequestStatus.SUCCESS, viewModel.state.value.glsServiceData.requestStatus)
|
||||
glsServer.continueWithResponse() //continue server breakpoint
|
||||
|
||||
assertEquals(RequestStatus.SUCCESS, viewModel.state.value.glsServiceData.requestStatus)
|
||||
assertEquals(1, viewModel.state.value.glsServiceData.records.size)
|
||||
|
||||
val parsedResponse = GlucoseMeasurementParser.parse(glsServer.YOUNGEST_RECORD)
|
||||
assertEquals(parsedResponse, viewModel.state.value.glsServiceData.records.keys.first())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when request last record then change status and get 1 record`() = runTest {
|
||||
viewModel.handleResult(NavigationResult.Success(device))
|
||||
advanceUntilIdle() //Needed because of delay() in waitForBonding()
|
||||
assertEquals(RequestStatus.IDLE, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
viewModel.onEvent(OnWorkingModeSelected(WorkingMode.LAST))
|
||||
assertEquals(RequestStatus.PENDING, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
glsServer.continueWithResponse() //continue server breakpoint
|
||||
|
||||
assertEquals(RequestStatus.SUCCESS, viewModel.state.value.glsServiceData.requestStatus)
|
||||
assertEquals(1, viewModel.state.value.glsServiceData.records.size)
|
||||
|
||||
val parsedResponse = GlucoseMeasurementParser.parse(glsServer.OLDEST_RECORD)
|
||||
assertEquals(parsedResponse, viewModel.state.value.glsServiceData.records.keys.first())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when request all record then change status and get 5 records`() = runTest {
|
||||
viewModel.handleResult(NavigationResult.Success(device))
|
||||
advanceUntilIdle() //Needed because of delay() in waitForBonding()
|
||||
assertEquals(RequestStatus.IDLE, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
viewModel.onEvent(OnWorkingModeSelected(WorkingMode.ALL))
|
||||
assertEquals(RequestStatus.PENDING, viewModel.state.value.glsServiceData.requestStatus)
|
||||
|
||||
glsServer.continueWithResponse() //continue server breakpoint
|
||||
advanceUntilIdle() //We have to use because of delay() in sendAll()
|
||||
|
||||
assertEquals(RequestStatus.SUCCESS, viewModel.state.value.glsServiceData.requestStatus)
|
||||
assertEquals(5, viewModel.state.value.glsServiceData.records.size)
|
||||
|
||||
val expectedRecords = glsServer.records.map { GlucoseMeasurementParser.parse(it) }
|
||||
assertContentEquals(expectedRecords, viewModel.state.value.glsServiceData.records.keys)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ dependencyResolutionManagement {
|
||||
}
|
||||
versionCatalogs {
|
||||
create("libs") {
|
||||
from("no.nordicsemi.android.gradle:version-catalog:1.5.5")
|
||||
from("no.nordicsemi.android.gradle:version-catalog:1.5.8")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user