Skip to content

Commit

Permalink
AC-1091: Add Tests for Encounter Repository (#1009)
Browse files Browse the repository at this point in the history
* AC-1091: Add tests for EncounterRepository

* -added more tests for EncounterRepository and fixed discovered bugs

* -To trigger the Unit Test CI

---------

Co-authored-by: shubham sharma <[email protected]>
  • Loading branch information
shubhamsgit and shubham sharma authored Aug 15, 2023
1 parent 27033e0 commit 6191553
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import javax.inject.Singleton

@Singleton
class EncounterRepository @Inject constructor(
private val visitRepository: VisitRepository,
private val encounterDAO: EncounterDAO
val visitRepository: VisitRepository,
val encounterDAO: EncounterDAO
) : BaseRepository() {

val encounterRoomDAO: EncounterRoomDAO = AppDatabase.getDatabase(
Expand Down Expand Up @@ -145,19 +145,8 @@ class EncounterRepository @Inject constructor(

val encounterResources: List<Resource> = this.body()!!.results
for (encounterResource in encounterResources) {
getEncounterByUuid(encounterResource.uuid!!).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ encounter ->
encounterList.add(encounter)
},
{ error ->
Log.e("Encounter Repository", "Error: ${error.message}")
},
{
Log.d("Encounter Repository", "Observable completed")
}
)
val encounter = getEncounterByUuid(encounterResource.uuid!!).execute()
encounterList.add(encounter)
}
encounterDAO.deleteAllStandaloneEncounters(uuid) //delete previous list
encounterDAO.saveStandaloneEncounters(encounterList) //save latest list
Expand All @@ -176,23 +165,8 @@ class EncounterRepository @Inject constructor(
*/
fun getAllEncounterResourcesByVisitUuid(visitUuid: String): Observable<Resource>? {
var encounterResourceList: List<Resource> = mutableListOf()
var fetchedVisit: Visit? = null

visitRepository.getVisit(visitUuid).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ visit ->
fetchedVisit = visit
},
{ error ->
Log.e("Visit Repository", "Error: ${error.message}")
},
{
Log.d("Visit Repository", "Observable completed")
}
)

if(fetchedVisit != null) encounterResourceList = fetchedVisit!!.encounters
val fetchedVisit: Visit? = visitRepository.getVisit(visitUuid).execute()
if(fetchedVisit != null) encounterResourceList = fetchedVisit.encounters

return Observable.from(encounterResourceList)
}
Expand Down Expand Up @@ -270,19 +244,8 @@ class EncounterRepository @Inject constructor(

val encounterResources: List<Resource> = this.body()!!.results
for (encounterResource in encounterResources) {
getEncounterByUuid(encounterResource.uuid!!).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ encounter ->
encounterList.add(encounter)
},
{ error ->
Log.e("Encounter Repository", "Error: ${error.message}")
},
{
Log.d("Encounter Repository", "Observable completed")
}
)
val encounter = getEncounterByUuid(encounterResource.uuid!!).execute()
encounterList.add(encounter)
}

saveLocallyIfNotExist(encounterList)
Expand Down Expand Up @@ -319,19 +282,8 @@ class EncounterRepository @Inject constructor(

val encounterResources: List<Resource> = this.body()!!.results
for (encounterResource in encounterResources) {
getEncounterByUuid(encounterResource.uuid!!).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ encounter ->
encounterList.add(encounter)
},
{ error ->
Log.e("Encounter Repository", "Error: ${error.message}")
},
{
Log.d("Encounter Repository", "Observable completed")
}
)
val encounter = getEncounterByUuid(encounterResource.uuid!!).execute()
encounterList.add(encounter)
}

saveLocallyIfNotExist(encounterList)
Expand Down Expand Up @@ -368,19 +320,8 @@ class EncounterRepository @Inject constructor(

val encounterResources: List<Resource> = this.body()!!.results
for (encounterResource in encounterResources) {
getEncounterByUuid(encounterResource.uuid!!).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ encounter ->
encounterList.add(encounter)
},
{ error ->
Log.e("Encounter Repository", "Error: ${error.message}")
},
{
Log.d("Encounter Repository", "Observable completed")
}
)
val encounter = getEncounterByUuid(encounterResource.uuid!!).execute()
encounterList.add(encounter)
}

saveLocallyIfNotExist(encounterList)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package com.openmrs.android_sdk.library.api.repository

import android.content.Context
import com.google.gson.GsonBuilder
import com.openmrs.android_sdk.library.OpenmrsAndroid
import com.openmrs.android_sdk.library.api.RestApi
import com.openmrs.android_sdk.library.dao.LocationRoomDAO
import com.openmrs.android_sdk.library.dao.VisitRoomDAO
import com.openmrs.android_sdk.library.dao.EncounterRoomDAO
import com.openmrs.android_sdk.library.dao.EncounterTypeRoomDAO
import com.openmrs.android_sdk.library.dao.ObservationRoomDAO
import com.openmrs.android_sdk.library.dao.EncounterDAO
import com.openmrs.android_sdk.library.dao.PatientDAO
import com.openmrs.android_sdk.library.dao.PatientRoomDAO
import com.openmrs.android_sdk.library.dao.VisitDAO
import com.openmrs.android_sdk.library.databases.AppDatabase
import com.openmrs.android_sdk.library.databases.entities.StandaloneEncounterEntity
import com.openmrs.android_sdk.library.models.Patient
import com.openmrs.android_sdk.library.models.Obscreate
import com.openmrs.android_sdk.library.models.Encountercreate
import com.openmrs.android_sdk.library.models.EncounterProviderCreate
import com.openmrs.android_sdk.library.models.Visit
import com.openmrs.android_sdk.utilities.NetworkUtils
import com.openmrs.android_sdk.utilities.execute
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import io.mockk.*
import io.reactivex.Single
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okio.buffer
import okio.source
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import rx.Observable
import javax.inject.Inject

@HiltAndroidTest
@RunWith(RobolectricTestRunner::class)
@Config(application = HiltTestApplication::class)
class EncounterRepositoryTest {
lateinit var mockWebServer: MockWebServer
lateinit var encounterApi: RestApi

@get:Rule
var hiltRule = HiltAndroidRule(this)

val context: Context = mockk(relaxed = true)
val appContext: Context = mockk(relaxed = true)
val appDatabase: AppDatabase = mockk()
val locationRoomDAO: LocationRoomDAO = mockk()
val encounterRoomDAO: EncounterRoomDAO = mockk(relaxed = true)
val visitRoomDAO: VisitRoomDAO = mockk()
val encounterDAO: EncounterDAO = mockk(relaxed = true)
val encounterTypeRoomDAO: EncounterTypeRoomDAO = mockk()
val observationRoomDAO: ObservationRoomDAO = mockk()
val patientRoomDAO: PatientRoomDAO = mockk()
val encounterCreate = Encountercreate()

@Before
fun init() {
encounterCreate.id = 1
encounterCreate.visit = "Some visit"
encounterCreate.patient = "Some patient"
encounterCreate.patientId = 1234
encounterCreate.encounterType = "Some encounter type"
encounterCreate.formname = "Some form name"
encounterCreate.synced = false
val obs1 = Obscreate()
obs1.value = "101"
obs1.concept = "Observation1"
val obs2 = Obscreate()
obs2.value = "102"
obs2.concept = "Observation2"
encounterCreate.observations = listOf(obs1, obs2)
encounterCreate.formUuid = "Some form UUID"
encounterCreate.location = "Some location"
val provider1 = EncounterProviderCreate("12345", "67890")
val provider2 = EncounterProviderCreate("abcd", "efgh")
encounterCreate.encounterProvider = listOf(provider1, provider2)

val standaloneEncounterEntity: StandaloneEncounterEntity = mockk(relaxed = true)
every { standaloneEncounterEntity.uuid } returns "d3360c01-9813-4ff8-bd81-909af6612632"
val listToReturn: List<StandaloneEncounterEntity> = listOf(standaloneEncounterEntity)
every { encounterRoomDAO.getAllStandAloneEncounters() } returns Single.just(listToReturn)

every { encounterDAO.saveStandaloneEncounters(any()) } returns listOf(1L,2L,3L)

mockkStatic(OpenmrsAndroid::class)
every { OpenmrsAndroid.getInstance() } returns context
every { context.getApplicationContext() } returns appContext
mockkStatic(AppDatabase::class)
every { AppDatabase.getDatabase(appContext) } returns appDatabase
every { appDatabase.locationRoomDAO() } returns locationRoomDAO
every { appDatabase.patientRoomDAO() } returns patientRoomDAO
every { appDatabase.encounterRoomDAO() } returns encounterRoomDAO
every { appDatabase.visitRoomDAO() } returns visitRoomDAO
every { appDatabase.encounterTypeRoomDAO() } returns encounterTypeRoomDAO
every { appDatabase.observationRoomDAO() } returns observationRoomDAO

val patient: Patient = mockk(relaxed = true)
every { patient.isSynced } returns true

val visit: Visit = mockk(relaxed = true)
every { visit.uuid } returns "fakeUuid"

mockkConstructor(PatientDAO::class)
every { anyConstructed<PatientDAO>().findPatientByID("1234") } returns patient

val fakeObservable: Observable<Visit> = mockk(relaxed = true)
every { fakeObservable.execute() } returns visit

mockkConstructor(VisitDAO::class)
every { anyConstructed<VisitDAO>().getActiveVisitByPatientId(1234) } returns fakeObservable

mockkStatic(NetworkUtils::class)
every { NetworkUtils.isOnline() } returns true

mockWebServer = MockWebServer()
mockWebServer.start()

val gsonBuilder = GsonBuilder()
val myGson = gsonBuilder
.excludeFieldsWithoutExposeAnnotation()
.create()

val retrofit = Retrofit.Builder()
.baseUrl(mockWebServer.url("/"))
.addConverterFactory(GsonConverterFactory.create(myGson))
.build()

encounterApi = retrofit.create(RestApi::class.java)
hiltRule.inject()
}

@After
fun tearDown() {
clearAllMocks()
mockWebServer.shutdown()
}

@Inject
lateinit var encounterRepository: EncounterRepository

@Test
fun `getAllEncounterResourcesByPatientUuid success return List of resources`(){
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterResourcesGet-success.json")

encounterRepository.restApi = encounterApi
val patientUuid = "96be32d2-9367-4d1d-a285-79a5e5db12b8"
val resourceList = encounterRepository.getAllEncounterResourcesByPatientUuid(patientUuid).toBlocking().first()
val testResource = resourceList.get(2)

assertEquals(testResource.uuid, "0cc4a9e5-d44a-461e-ad64-0f04817c5bd0")
assertEquals(testResource.display, "Vitals 19/04/2015")
}

@Test
fun `getAllEncountersByPatientUuidAndSaveLocally success returns List of Encounters`(){
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterResourcesGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")

encounterRepository.restApi = encounterApi
val patientUuid = "96be32d2-9367-4d1d-a285-79a5e5db12b8"
val resourceList = encounterRepository.getAllEncountersByPatientUuidAndSaveLocally(patientUuid).toBlocking().first()
val testResource = resourceList.get(1)

assertEquals(testResource.uuid, "d3360c01-9813-4ff8-bd81-909af6612632")
assertEquals(testResource.display, "Vitals 24/02/2015")
}

@Test
fun `getAllEncounterResourcesByVisitUuid success returns encounters`(){
enqueueMockResponse("mocked_responses/EncounterRepository/VisitGet-success.json")

encounterRepository.visitRepository.restApi = encounterApi
val visitUuid = "4d67b954-216a-4b19-9cab-94c59cc5b705"
val encounter = encounterRepository.getAllEncounterResourcesByVisitUuid(visitUuid)!!.toBlocking().first()

assertEquals(encounter.uuid, "1ef9e5ee-ca7a-4a4b-852c-42c107526f81")
assertEquals(encounter.display, "Discharge 11/12/2016")
}

@Test
fun `getAllEncountersByPatientUuidAndEncounterTypeAndSaveLocally success returns List of encounters`(){
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterResourcesGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")
enqueueMockResponse("mocked_responses/EncounterRepository/EncounterGet-success.json")

encounterRepository.restApi = encounterApi
val patientUuid = "96be32d2-9367-4d1d-a285-79a5e5db12b8"
val encounterTypeUuid = "67a71486-1a54-468f-ac3e-7091a9a79584"

val resourceList = encounterRepository.getAllEncountersByPatientUuidAndEncounterTypeAndSaveLocally(patientUuid, encounterTypeUuid).toBlocking().first()
val testResource = resourceList.get(1)

assertEquals(testResource.uuid, "d3360c01-9813-4ff8-bd81-909af6612632")
assertEquals(testResource.display, "Vitals 24/02/2015")
}

fun enqueueMockResponse(fileName: String) {
javaClass.classLoader?.let {
val inputStream = it.getResourceAsStream(fileName)
val source = inputStream.source().buffer()
val mockResponse = MockResponse()
mockResponse.setBody(source.readString(Charsets.UTF_8))
mockResponse.setResponseCode(200)
mockWebServer.enqueue(mockResponse)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
package com.openmrs.android_sdk.library.api.repository.di.modules

import android.content.Context
import com.openmrs.android_sdk.library.api.repository.VisitRepository
import com.openmrs.android_sdk.library.dao.AllergyRoomDAO
import com.openmrs.android_sdk.library.dao.AppointmentRoomDAO
import com.openmrs.android_sdk.library.dao.ConceptRoomDAO
import com.openmrs.android_sdk.library.dao.EncounterCreateRoomDAO
import com.openmrs.android_sdk.library.dao.EncounterDAO
import com.openmrs.android_sdk.library.dao.ProviderRoomDAO
import com.openmrs.android_sdk.library.databases.AppDatabase
import com.openmrs.android_sdk.library.di.modules.AppDatabaseModule
Expand All @@ -26,6 +29,9 @@ import dagger.Provides
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dagger.hilt.testing.TestInstallIn
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import javax.inject.Singleton

Expand All @@ -38,7 +44,16 @@ object FakeAppDatabaseModule {

@Provides
@Singleton
fun provideFakeAppDatabase(@ApplicationContext context: Context): AppDatabase = mockk()
fun provideFakeAppDatabase(@ApplicationContext context: Context): AppDatabase {
val encounterCreateRoomDAO: EncounterCreateRoomDAO = mockk()
val appDatabase: AppDatabase = mockk()
every { appDatabase.encounterCreateRoomDAO() } returns encounterCreateRoomDAO
every { encounterCreateRoomDAO.updateExistingEncounter(any()) } just Runs
every { encounterCreateRoomDAO.getCreatedEncountersByID(any()) } returns mockk()


return appDatabase
}

@Provides
@Singleton
Expand Down
Loading

0 comments on commit 6191553

Please sign in to comment.