/* * Copyright (c) 2014. The Trustees of Indiana University. * * This version of the code is licensed under the MPL 2.0 Open Source license with additional * healthcare disclaimer. If the user is an entity intending to commercialize any application * that uses this code in a for-profit venture, please contact the copyright holder. */ package com.muzima.service; import android.content.SharedPreferences; import com.muzima.MuzimaApplication; import com.muzima.api.context.Context; import com.muzima.api.model.Cohort; import com.muzima.api.model.CohortData; import com.muzima.api.model.CohortMember; import com.muzima.api.model.Concept; import com.muzima.api.model.Encounter; import com.muzima.api.model.Form; import com.muzima.api.model.FormTemplate; import com.muzima.api.model.Observation; import com.muzima.api.model.Patient; import com.muzima.api.model.User; import com.muzima.controller.CohortController; import com.muzima.controller.ConceptController; import com.muzima.controller.EncounterController; import com.muzima.controller.FormController; import com.muzima.controller.ObservationController; import com.muzima.controller.PatientController; import com.muzima.controller.ProviderController; import com.muzima.utils.Constants; import org.apache.lucene.queryParser.ParseException; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.io.IOException; import java.net.ConnectException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import static com.muzima.controller.ObservationController.ReplaceObservationException; import static com.muzima.utils.Constants.COHORT_PREFIX_PREF; import static com.muzima.utils.Constants.DataSyncServiceConstants.SyncStatusConstants; import static java.util.Arrays.asList; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class MuzimaSyncServiceTest { private MuzimaSyncService muzimaSyncService; private MuzimaApplication muzimaApplication; private Context muzimaContext; private FormController formController; private CohortController cohortController; private SharedPreferences sharedPref; private PatientController patientController; private ObservationController observationController; private ConceptController conceptController; private EncounterController encounterController; private CohortPrefixPreferenceService prefixesPreferenceService; @Before public void setUp() throws Exception { muzimaApplication = mock(MuzimaApplication.class); muzimaContext = mock(Context.class); formController = mock(FormController.class); cohortController = mock(CohortController.class); patientController = mock(PatientController.class); observationController = mock(ObservationController.class); sharedPref = mock(SharedPreferences.class); conceptController = mock(ConceptController.class); encounterController = mock(EncounterController.class); prefixesPreferenceService = mock(CohortPrefixPreferenceService.class); ProviderController providerController = mock(ProviderController.class); User authenticatedUser = mock(User.class); authenticatedUser.setSystemId("12345"); when(muzimaApplication.getAuthenticatedUser()).thenReturn(authenticatedUser); when(muzimaApplication.getMuzimaContext()).thenReturn(muzimaContext); when(muzimaApplication.getFormController()).thenReturn(formController); when(muzimaApplication.getCohortController()).thenReturn(cohortController); when(muzimaApplication.getPatientController()).thenReturn(patientController); when(muzimaApplication.getProviderController()).thenReturn(providerController); when(muzimaApplication.getObservationController()).thenReturn(observationController); when(muzimaApplication.getConceptController()).thenReturn(conceptController); when(muzimaApplication.getEncounterController()).thenReturn(encounterController); when(muzimaApplication.getCohortPrefixesPreferenceService()).thenReturn(prefixesPreferenceService); when(muzimaApplication.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPref); when(muzimaApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application); muzimaSyncService = new MuzimaSyncService(muzimaApplication); } @Test public void authenticate_shouldReturnSuccessStatusIfAuthenticated() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; assertThat(muzimaSyncService.authenticate(credentials), is(SyncStatusConstants.AUTHENTICATION_SUCCESS)); } @Test public void authenticate_shouldAuthenticateIfNotAlreadyAuthenticated() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; when(muzimaContext.isAuthenticated()).thenReturn(true); verify(muzimaContext, times(0)).authenticate(anyString(), anyString(), anyString(), anyBoolean()); assertThat(muzimaSyncService.authenticate(credentials), is(SyncStatusConstants.AUTHENTICATION_SUCCESS)); } @Test public void authenticate_shouldCallCloseSessionIfAuthenticationSucceed() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; muzimaSyncService.authenticate(credentials); verify(muzimaContext).closeSession(); } @Test public void authenticate_shouldCallCloseSessionIfExceptionOccurred() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; doThrow(new ParseException()).when(muzimaContext).authenticate(credentials[0], credentials[1], credentials[2], false); muzimaSyncService.authenticate(credentials); verify(muzimaContext).closeSession(); } @Test public void authenticate_shouldReturnParsingErrorIfParsingExceptionOccurs() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; doThrow(new ParseException()).when(muzimaContext).authenticate(credentials[0], credentials[1], credentials[2], false); assertThat(muzimaSyncService.authenticate(credentials), is(SyncStatusConstants.PARSING_ERROR)); } @Test public void authenticate_shouldReturnConnectionErrorIfConnectionErrorOccurs() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; doThrow(new ConnectException()).when(muzimaContext).authenticate(credentials[0], credentials[1], credentials[2], false); assertThat(muzimaSyncService.authenticate(credentials), is(SyncStatusConstants.SERVER_CONNECTION_ERROR)); } @Test public void authenticate_shouldReturnAuthenticationErrorIfAuthenticationErrorOccurs() throws Exception { String[] credentials = new String[]{"username", "password", "url"}; doThrow(new IOException()).when(muzimaContext).authenticate(credentials[0], credentials[1], credentials[2], false); assertThat(muzimaSyncService.authenticate(credentials), is(SyncStatusConstants.AUTHENTICATION_ERROR)); } @Test public void downloadForms_shouldReplaceOldForms() throws Exception, FormController.FormFetchException, FormController.FormDeleteException, FormController.FormSaveException { List<Form> forms = new ArrayList<>(); when(formController.downloadAllForms()).thenReturn(forms); muzimaSyncService.downloadForms(); verify(formController).downloadAllForms(); verify(formController).updateAllForms(forms); } @Test public void downloadForms_shouldReturnSuccessStatusAndDownloadCountIfSuccessful() throws Exception, FormController.FormFetchException { int[] result = new int[]{SyncStatusConstants.SUCCESS, 2, 0}; List<Form> forms = new ArrayList<Form>() {{ add(new Form()); add(new Form()); }}; when(formController.downloadAllForms()).thenReturn(forms); assertThat(muzimaSyncService.downloadForms(), is(result)); } @Test public void downloadForms_shouldReturnDeletedFormCount() throws FormController.FormFetchException { int[] result = new int[]{SyncStatusConstants.SUCCESS, 2, 1}; List<Form> downloadedForms = new ArrayList<>(); Form formToDelete = new Form(); formToDelete.setRetired(true); formToDelete.setUuid("123"); Form newForm = new Form(); newForm.setRetired(false); newForm.setUuid("456"); downloadedForms.add(formToDelete); downloadedForms.add(new Form()); downloadedForms.add(newForm); List<Form> allAvailableForms = new ArrayList<>(); Form formA = new Form(); formA.setUuid("789"); allAvailableForms.add(formToDelete); allAvailableForms.add(formA); when(formController.downloadAllForms()).thenReturn(downloadedForms); when(formController.getAllAvailableForms()).thenReturn(allAvailableForms); assertThat(muzimaSyncService.downloadForms(), is(result)); } @Test public void downloadForms_shouldReturnDownloadErrorIfDownloadExceptionOccur() throws Exception, FormController.FormFetchException { doThrow(new FormController.FormFetchException(null)).when(formController).downloadAllForms(); assertThat(muzimaSyncService.downloadForms()[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); } @Test public void downloadForms_shouldReturnSaveErrorIfSaveExceptionOccur() throws Exception, FormController.FormSaveException { doThrow(new FormController.FormSaveException(null)).when(formController).updateAllForms(anyList()); assertThat(muzimaSyncService.downloadForms()[0], is(SyncStatusConstants.SAVE_ERROR)); } @Test public void downloadFormTemplates_shouldReplaceDownloadedTemplates() throws FormController.FormFetchException, FormController.FormSaveException { String[] formTemplateUuids = new String[]{}; List<FormTemplate> formTemplates = new ArrayList<>(); when(formController.downloadFormTemplates(formTemplateUuids)).thenReturn(formTemplates); SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); when(sharedPref.edit()).thenReturn(editor); muzimaSyncService.downloadFormTemplates(formTemplateUuids,true); verify(formController).downloadFormTemplates(formTemplateUuids); verify(formController).replaceFormTemplates(formTemplates); } @Test public void downloadFormTemplates_shouldReturnSuccessStatusAndDownloadCountIfSuccessful() throws FormController.FormFetchException { int[] result = new int[]{SyncStatusConstants.SUCCESS, 2, 0, 0}; List<FormTemplate> formTemplates = new ArrayList<FormTemplate>() {{ FormTemplate formTemplate = new FormTemplate(); formTemplate.setHtml("<html></html>"); add(formTemplate); add(formTemplate); }}; String[] formIds = {}; when(formController.downloadFormTemplates(formIds)).thenReturn(formTemplates); SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); when(sharedPref.edit()).thenReturn(editor); assertThat(muzimaSyncService.downloadFormTemplates(formIds, true), is(result)); } @Test public void downloadFormTemplates_shouldReturnDownloadErrorIfDownloadExceptionOccur() throws FormController.FormFetchException { String[] formUuids = {}; doThrow(new FormController.FormFetchException(null)).when(formController).downloadFormTemplates(formUuids); assertThat(muzimaSyncService.downloadFormTemplates(formUuids,true)[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); } @Test public void downloadFormTemplates_shouldReturnSaveErrorIfSaveExceptionOccur() throws FormController.FormSaveException, FormController.FormFetchException { String[] formUuids = {}; doThrow(new FormController.FormSaveException(null)).when(formController).replaceFormTemplates(anyList()); assertThat(muzimaSyncService.downloadFormTemplates(formUuids,true)[0], is(SyncStatusConstants.SAVE_ERROR)); } @Test public void downloadCohort_shouldDownloadAllCohortsWhenNoPrefixesAreAvailableAndReplaceOldCohorts() throws Exception, CohortController.CohortDownloadException, CohortController.CohortDeleteException, CohortController.CohortSaveException { List<Cohort> cohorts = new ArrayList<>(); when(cohortController.downloadAllCohorts()).thenReturn(cohorts); when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.COHORT_PREFIX_PREF_KEY, new HashSet<String>())).thenReturn(new HashSet<String>()); muzimaSyncService.downloadCohorts(); verify(cohortController).downloadAllCohorts(); verify(cohortController).saveAllCohorts(cohorts); verify(cohortController).deleteCohorts(new ArrayList<Cohort>()); verifyNoMoreInteractions(cohortController); } @Test public void shouldDeleteVoidedCohortsWhenDownloading() throws CohortController.CohortDownloadException, CohortController.CohortSaveException, CohortController.CohortDeleteException { List<Cohort> cohorts = new ArrayList<>(); Cohort aCohort = mock(Cohort.class); Cohort voidedCohort = mock(Cohort.class); when(voidedCohort.isVoided()).thenReturn(true); when(aCohort.isVoided()).thenReturn(false); cohorts.add(aCohort); cohorts.add(voidedCohort); when(cohortController.downloadAllCohorts()).thenReturn(cohorts); when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.COHORT_PREFIX_PREF_KEY, new HashSet<String>())).thenReturn(new HashSet<String>()); muzimaSyncService.downloadCohorts(); verify(cohortController).deleteCohorts(Collections.singletonList(voidedCohort)); verify(cohortController).saveAllCohorts(Collections.singletonList(aCohort)); } @Test public void downloadCohort_shouldDownloadOnlyPrefixedCohortsWhenPrefixesAreAvailableAndReplaceOldCohorts() throws Exception, CohortController.CohortDownloadException, CohortController.CohortDeleteException, CohortController.CohortSaveException { List<Cohort> cohorts = new ArrayList<>(); List<String> cohortPrefixes = new ArrayList<String>() {{ add("Pref1"); add("Pref2"); }}; when(cohortController.downloadAllCohorts()).thenReturn(cohorts); when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(prefixesPreferenceService.getCohortPrefixes()).thenReturn(cohortPrefixes); muzimaSyncService.downloadCohorts(); verify(cohortController).downloadCohortsByPrefix(cohortPrefixes); verify(cohortController).saveAllCohorts(cohorts); verify(cohortController).deleteCohorts(new ArrayList<Cohort>()); verifyNoMoreInteractions(cohortController); } @Test public void downloadCohort_shouldReturnSuccessStatusAndDownloadCountIfSuccessful() throws Exception, CohortController.CohortDownloadException { List<Cohort> cohorts = new ArrayList<Cohort>() {{ add(new Cohort()); add(new Cohort()); }}; int[] result = new int[]{SyncStatusConstants.SUCCESS, 2, 0}; when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.COHORT_PREFIX_PREF_KEY, new HashSet<String>())).thenReturn(new HashSet<String>()); when(cohortController.downloadAllCohorts()).thenReturn(cohorts); assertThat(muzimaSyncService.downloadCohorts(), is(result)); } @Test public void downloadCohort_shouldReturnDownloadErrorIfDownloadExceptionOccurs() throws Exception, CohortController.CohortDownloadException { when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.COHORT_PREFIX_PREF_KEY, new HashSet<String>())).thenReturn(new HashSet<String>()); doThrow(new CohortController.CohortDownloadException(null)).when(cohortController).downloadAllCohorts(); assertThat(muzimaSyncService.downloadCohorts()[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); } @Test public void downloadCohort_shouldReturnSaveErrorIfSaveExceptionOccurs() throws Exception, CohortController.CohortSaveException { when(muzimaApplication.getSharedPreferences(COHORT_PREFIX_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.COHORT_PREFIX_PREF_KEY, new HashSet<String>())).thenReturn(new HashSet<String>()); doThrow(new CohortController.CohortSaveException(null)).when(cohortController).saveAllCohorts(new ArrayList<Cohort>()); assertThat(muzimaSyncService.downloadCohorts()[0], is(SyncStatusConstants.SAVE_ERROR)); } @Test public void downloadPatientsForCohorts_shouldDownloadAndReplaceCohortMembersAndPatients() throws Exception, CohortController.CohortDownloadException, CohortController.CohortReplaceException, PatientController.PatientSaveException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; List<CohortData> cohortDataList = new ArrayList<CohortData>() {{ add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); }}; when(cohortController.downloadCohortData(cohortUuids)).thenReturn(cohortDataList); muzimaSyncService.downloadPatientsForCohorts(cohortUuids); verify(cohortController).downloadCohortData(cohortUuids); verify(cohortController).addCohortMembers(cohortDataList.get(0).getCohortMembers()); verify(cohortController).addCohortMembers(cohortDataList.get(1).getCohortMembers()); verify(patientController).replacePatients(cohortDataList.get(0).getPatients()); verify(patientController).replacePatients(cohortDataList.get(1).getPatients()); verifyNoMoreInteractions(cohortController); } @Test public void shouldDeleteVoidedPatientsDuringPatientDownload() throws Exception, CohortController.CohortDownloadException, PatientController.PatientDeleteException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; final Patient voidedPatient = mock(Patient.class); when(voidedPatient.isVoided()).thenReturn(true); List<CohortData> cohortDataList = new ArrayList<CohortData>() {{ add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); addPatient(voidedPatient); }}); add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); }}; when(cohortController.downloadCohortData(cohortUuids)).thenReturn(cohortDataList); muzimaSyncService.downloadPatientsForCohorts(cohortUuids); verify(patientController).deletePatient(Collections.singletonList(voidedPatient)); } @Test public void downloadPatientsForCohorts_shouldReturnSuccessStatusAndCohortAndPatinetCountIfDownloadIsSuccessful() throws Exception, CohortController.CohortDownloadException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; List<CohortData> cohortDataList = new ArrayList<CohortData>() {{ add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); addPatient(new Patient()); }}); }}; when(cohortController.downloadCohortData(cohortUuids)).thenReturn(cohortDataList); int[] result = muzimaSyncService.downloadPatientsForCohorts(cohortUuids); assertThat(result[0], is(SyncStatusConstants.SUCCESS)); assertThat(result[1], is(3)); assertThat(result[2], is(2)); } @Test public void downloadPatientsForCohorts_shouldReturnDownloadErrorIfDownloadExceptionIsThrown() throws CohortController.CohortDownloadException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; doThrow(new CohortController.CohortDownloadException(null)).when(cohortController).downloadCohortData(cohortUuids); assertThat(muzimaSyncService.downloadPatientsForCohorts(cohortUuids)[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); } @Test public void downloadPatientsForCohorts_shouldReturnReplaceErrorIfReplaceExceptionIsThrownForCohorts() throws CohortController.CohortReplaceException, CohortController.CohortDownloadException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; List<CohortData> cohortDataList = new ArrayList<CohortData>() {{ add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); addPatient(new Patient()); }}); }}; when(cohortController.downloadCohortData(cohortUuids)).thenReturn(cohortDataList); doThrow(new CohortController.CohortReplaceException(null)).when(cohortController).addCohortMembers(anyList()); assertThat(muzimaSyncService.downloadPatientsForCohorts(cohortUuids)[0], is(SyncStatusConstants.REPLACE_ERROR)); } @Test public void downloadPatientsForCohorts_shouldReturnReplaceErrorIfReplaceExceptionIsThrownForPatients() throws CohortController.CohortDownloadException, PatientController.PatientSaveException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; List<CohortData> cohortDataList = new ArrayList<CohortData>() {{ add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); }}); add(new CohortData() {{ addCohortMember(new CohortMember()); addPatient(new Patient()); addPatient(new Patient()); }}); }}; when(cohortController.downloadCohortData(cohortUuids)).thenReturn(cohortDataList); doThrow(new PatientController.PatientSaveException(null)).when(patientController).replacePatients(anyList()); assertThat(muzimaSyncService.downloadPatientsForCohorts(cohortUuids)[0], is(SyncStatusConstants.REPLACE_ERROR)); } @Test public void downloadObservationsForPatients_shouldDownloadObservationsForGiveCohortIdsAndSavedConcepts() throws Exception, PatientController.PatientLoadException, ObservationController.DownloadObservationException, ObservationController.ReplaceObservationException, ConceptController.ConceptFetchException, ObservationController.DeleteObservationException { String[] cohortUuids = new String[]{"uuid1", "uuid2"}; List<Patient> patients = new ArrayList<Patient>() {{ add(new Patient() {{ setUuid("patient1"); }}); }}; List<Observation> allObservations = new ArrayList<Observation>() {{ add(new Observation()); add(new Observation()); }}; when(patientController.getPatientsForCohorts(cohortUuids)).thenReturn(patients); when(muzimaApplication.getSharedPreferences(Constants.CONCEPT_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); List<String> patientUuids = Collections.singletonList("patient1"); List<String> conceptUuids = asList("weight", "temp"); when(observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids)) .thenReturn(allObservations); Concept conceptWeight = new Concept(); conceptWeight.setUuid("weight"); Concept conceptTemp = new Concept(); conceptTemp.setUuid("temp"); when(conceptController.getConcepts()).thenReturn(asList(conceptWeight, conceptTemp)); muzimaSyncService.downloadObservationsForPatientsByCohortUUIDs(cohortUuids,true); verify(observationController).downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids); verify(observationController).deleteObservations(new ArrayList<Observation>()); verify(observationController).replaceObservations(allObservations); verifyNoMoreInteractions(observationController); } @Test public void downloadObservationsForPatients_shouldReturnSuccessAndCountWhenDownloadingObservationsForPatient() throws Exception, PatientController.PatientLoadException, ObservationController.DownloadObservationException, ConceptController.ConceptFetchException { String[] cohortUuids = new String[]{"uuid1"}; List<Patient> patients = new ArrayList<Patient>() {{ add(new Patient() {{ setUuid("patient1"); }}); }}; List<Observation> allObservations = new ArrayList<Observation>() {{ add(new Observation()); add(new Observation()); }}; when(patientController.getPatientsForCohorts(cohortUuids)).thenReturn(patients); List<String> conceptUuids = Collections.singletonList("weight"); Concept conceptWeight = new Concept(); conceptWeight.setUuid("weight"); when(conceptController.getConcepts()).thenReturn(Collections.singletonList(conceptWeight)); when(observationController.downloadObservationsByPatientUuidsAndConceptUuids(Collections.singletonList("patient1"), conceptUuids)) .thenReturn(allObservations); int[] result = muzimaSyncService.downloadObservationsForPatientsByCohortUUIDs(cohortUuids,true); assertThat(result[0], is(SyncStatusConstants.SUCCESS)); assertThat(result[1], is(2)); } @Test public void downloadObservationsForPatients_shouldReturnLoadErrorWhenLoadExceptionIsThrownForObservations() throws Exception, PatientController.PatientLoadException { String[] cohortUuids = new String[]{}; doThrow(new PatientController.PatientLoadException(null)).when(patientController).getPatientsForCohorts(cohortUuids); int[] result = muzimaSyncService.downloadObservationsForPatientsByCohortUUIDs(cohortUuids,true); assertThat(result[0], is(SyncStatusConstants.LOAD_ERROR)); } @Test public void downloadObservationsForPatients_shouldReturnDownloadErrorWhenDownloadExceptionIsThrownForObservations() throws Exception, ObservationController.DownloadObservationException, PatientController.PatientLoadException, ConceptController.ConceptFetchException { String[] cohortUuids = new String[]{"uuid1"}; List<Patient> patients = new ArrayList<Patient>() {{ add(new Patient() {{ setUuid("patient1"); }}); }}; List<Concept> conceptList = new ArrayList<Concept>() {{ add(new Concept() {{ setUuid("concept1"); }}); }}; Set<String> concepts = new HashSet<String>() {{ add("weight"); }}; when(patientController.getPatientsForCohorts(cohortUuids)).thenReturn(patients); when(conceptController.getConcepts()).thenReturn(conceptList); when(muzimaApplication.getSharedPreferences(Constants.CONCEPT_PREF, android.content.Context.MODE_PRIVATE)).thenReturn(sharedPref); when(sharedPref.getStringSet(Constants.CONCEPT_PREF_KEY, new HashSet<String>())).thenReturn(concepts); doThrow(new ObservationController.DownloadObservationException(null)).when(observationController).downloadObservationsByPatientUuidsAndConceptUuids(anyList(), anyList()); int[] result = muzimaSyncService.downloadObservationsForPatientsByCohortUUIDs(cohortUuids,true); assertThat(result[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); } @Test public void downloadObservationsForPatients_shouldReturnReplaceErrorWhenReplaceExceptionIsThrownForObservations() throws Exception, ReplaceObservationException, ObservationController.DownloadObservationException, PatientController.PatientLoadException { String[] cohortUuids = new String[]{}; List<Patient> patients = new ArrayList<Patient>() {{ add(new Patient() {{ setUuid("patient1"); }}); }}; when(patientController.getPatientsForCohorts(cohortUuids)).thenReturn(patients); doThrow(new ObservationController.ReplaceObservationException(null)).when(observationController).replaceObservations(anyList()); int[] result = muzimaSyncService.downloadObservationsForPatientsByCohortUUIDs(cohortUuids,true); assertThat(result[0], is(SyncStatusConstants.REPLACE_ERROR)); } @Test public void downloadEncountersForPatients_shouldDownloadInBatch() throws Exception, ObservationController.DownloadObservationException, PatientController.PatientLoadException, EncounterController.ReplaceEncounterException, EncounterController.DownloadEncounterException { String[] cohortUuids = new String[]{"uuid1"}; List<Patient> patients = new ArrayList<Patient>() {{ add(new Patient() {{ setUuid("patient1"); }}); }}; List<Encounter> encounters = new ArrayList<Encounter>() {{ add(new Encounter()); }}; when(patientController.getPatientsForCohorts(cohortUuids)).thenReturn(patients); List<String> patientUuids = Collections.singletonList("patient1"); when(encounterController.downloadEncountersByPatientUuids(patientUuids)).thenReturn(encounters); muzimaSyncService.downloadEncountersForPatientsByCohortUUIDs(cohortUuids, true); verify(encounterController).downloadEncountersByPatientUuids(patientUuids); verify(encounterController).replaceEncounters(encounters); verifyNoMoreInteractions(observationController); } @Test public void shouldDeleteVoidedEncountersWhenDownloadingEncounters() throws EncounterController.DeleteEncounterException, EncounterController.DownloadEncounterException { String[] patientUuids = new String[]{"patientUuid1", "patientUuid2"}; List<Encounter> encounters = new ArrayList<>(); encounters.add(new Encounter()); Encounter voidedEncounter = mock(Encounter.class); when(voidedEncounter.isVoided()).thenReturn(true); encounters.add(voidedEncounter); when(encounterController.downloadEncountersByPatientUuids(asList(patientUuids))).thenReturn(encounters); muzimaSyncService.downloadEncountersForPatientsByPatientUUIDs(asList(patientUuids),true); verify(encounterController).deleteEncounters(Collections.singletonList(voidedEncounter)); } @Test public void consolidatePatients_shouldGetAllPatientsConsolidateSavePatientFromServerAndDeleteLocalPatient() throws Exception, PatientController.PatientSaveException { Patient localPatient = mock(Patient.class); Patient remotePatient = mock(Patient.class); when(patientController.consolidateTemporaryPatient(localPatient)).thenReturn(remotePatient); when(patientController.getAllPatientsCreatedLocallyAndNotSynced()).thenReturn(Collections.singletonList(localPatient)); muzimaSyncService.consolidatePatients(); verify(patientController).getAllPatientsCreatedLocallyAndNotSynced(); verify(patientController).consolidateTemporaryPatient(localPatient); verify(patientController).savePatient(remotePatient); verify(patientController).deletePatient(localPatient); } @Test public void shouldUpdatePatientsThatAreNotInCohorts() throws Exception, PatientController.PatientSaveException, PatientController.PatientDownloadException { Patient localPatient1 = patient("patientUUID1"); Patient localPatient2 = patient("patientUUID2"); Patient serverPatient1 = patient("patientUUID3"); when(patientController.getPatientsNotInCohorts()).thenReturn(asList(localPatient1, localPatient2)); when(patientController.downloadPatientByUUID("patientUUID1")).thenReturn(serverPatient1); when(patientController.downloadPatientByUUID("patientUUID2")).thenReturn(null); muzimaSyncService.updatePatientsNotPartOfCohorts(); verify(patientController).downloadPatientByUUID("patientUUID1"); verify(patientController).downloadPatientByUUID("patientUUID2"); verify(patientController).replacePatients(Collections.singletonList(serverPatient1)); } @Test public void shouldDownloadAndSavePatientsGivenByUUID() throws Exception, PatientController.PatientDownloadException, PatientController.PatientSaveException { Patient patient1 = patient("patientUUID1"); Patient patient2 = patient("patientUUID2"); String[] patientUUIDs = new String[]{"patientUUID1", "patientUUID2"}; when(patientController.downloadPatientByUUID("patientUUID1")).thenReturn(patient1); when(patientController.downloadPatientByUUID("patientUUID2")).thenReturn(patient2); int[] result = muzimaSyncService.downloadPatients(patientUUIDs); assertThat(result[0], is(SyncStatusConstants.SUCCESS)); assertThat(result[1], is(2)); verify(patientController).savePatients(asList(patient1, patient2)); } @Test public void shouldReturnFailureIfDownloadFails() throws Exception, PatientController.PatientDownloadException, PatientController.PatientSaveException { Patient patient1 = patient("patientUUID1"); String[] patientUUIDs = new String[]{"patientUUID1"}; when(patientController.downloadPatientByUUID("patientUUID1")).thenReturn(patient1); doThrow(new PatientController.PatientSaveException(new Throwable())).when(patientController).savePatients(Collections.singletonList(patient1)); int[] result = muzimaSyncService.downloadPatients(patientUUIDs); assertThat(result[0], is(SyncStatusConstants.DOWNLOAD_ERROR)); assertThat(result[1], is(0)); verify(patientController).savePatients(Collections.singletonList(patient1)); } @Test public void shouldDeleteVoidedObservationsWhenDownloadingObservations() throws ObservationController.DeleteObservationException, ObservationController.DownloadObservationException, ReplaceObservationException, ConceptController.ConceptFetchException { List<String> patientUuids = Collections.singletonList("patientUuid"); List<Observation> observations = new ArrayList<Observation>(); Observation anObservation = mock(Observation.class); when(anObservation.isVoided()).thenReturn(false); observations.add(anObservation); Observation voidedObservation = mock(Observation.class); when(voidedObservation.isVoided()).thenReturn(true); observations.add(voidedObservation); List<Concept> conceptList = new ArrayList<Concept>() {{ add(new Concept() {{ setUuid("concept1"); }}); }}; when(conceptController.getConcepts()).thenReturn(conceptList); when(observationController.downloadObservationsByPatientUuidsAndConceptUuids (eq(patientUuids), eq(Collections.singletonList("concept1")))).thenReturn(observations); muzimaSyncService.downloadObservationsForPatientsByPatientUUIDs(patientUuids,true); verify(observationController).deleteObservations(Collections.singletonList(voidedObservation)); verify(observationController).replaceObservations(Collections.singletonList(anObservation)); } private Patient patient(String patientUUID) { Patient patient1 = new Patient(); patient1.setUuid(patientUUID); return patient1; } }