diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c20ef1e7..c8b7d201 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,6 +6,10 @@ on: - '*' # tags: # - '!v*' + pull_request: + branches: + - '*' + types: [opened, synchronize, reopened] jobs: build: diff --git a/.gitignore b/.gitignore index 9fb66257..47792f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ proguard/ # Log Files *.log +# Java heap dump files +*.hprof + # Android Studio Navigation editor temp files .navigation/ diff --git a/claimManagement/build.gradle b/claimManagement/build.gradle index c3a245d7..8cd81622 100644 --- a/claimManagement/build.gradle +++ b/claimManagement/build.gradle @@ -180,6 +180,12 @@ android { packagingOptions { exclude 'META-INF/DEPENDENCIES' } + + testOptions { + unitTests { + includeAndroidResources = true + } + } } apollo { @@ -193,6 +199,13 @@ apollo { ] } +tasks.withType(Test).configureEach { + testLogging { + events "passed", "skipped", "failed" + exceptionFormat "full" + showStandardStreams = false + } +} // Apply custom flavours if(file('custom-flavours.gradle').exists()){ @@ -215,9 +228,13 @@ dependencies { implementation ('com.apollographql.apollo:apollo-android-support:2.5.14'){ because("Apollo 3+ only works with Kotlin coroutines") } - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:5.5.0' + testImplementation 'org.robolectric:robolectric:4.11.1' + testImplementation 'androidx.test:core:1.5.0' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'androidx.test:core:1.5.0' implementation group: 'com.squareup.picasso', name: 'picasso', version: '2.71828' implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '1.2.7' diff --git a/claimManagement/src/main/java/org/openimis/imisclaims/ClaimActivity.java b/claimManagement/src/main/java/org/openimis/imisclaims/ClaimActivity.java index e9894971..171629a8 100644 --- a/claimManagement/src/main/java/org/openimis/imisclaims/ClaimActivity.java +++ b/claimManagement/src/main/java/org/openimis/imisclaims/ClaimActivity.java @@ -712,7 +712,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } - private boolean isValidData() { + protected boolean isValidData() { if (etHealthFacility.getText().length() == 0) { showValidationDialog(etHealthFacility, getResources().getString(R.string.MissingHealthFacility)); @@ -793,7 +793,7 @@ private boolean isValidData() { return true; } - private boolean isValidInsureeNumber() { + protected boolean isValidInsureeNumber() { Escape escape = new Escape(); return escape.CheckCHFID(etInsureeNumber.getText().toString()); } @@ -811,7 +811,7 @@ protected void confirmNewDialog(String msg) { runOnUiThread(() -> showDialog(msg, (dialog, which) -> ClearForm(), (dialog, which) -> dialog.dismiss())); } - private boolean saveClaim() { + protected boolean saveClaim() { Intent intent = getIntent(); String claimUUID; if (intent.hasExtra(EXTRA_CLAIM_UUID)) { diff --git a/claimManagement/src/main/java/org/openimis/imisclaims/SynchronizeService.java b/claimManagement/src/main/java/org/openimis/imisclaims/SynchronizeService.java index f7593030..ce198bba 100644 --- a/claimManagement/src/main/java/org/openimis/imisclaims/SynchronizeService.java +++ b/claimManagement/src/main/java/org/openimis/imisclaims/SynchronizeService.java @@ -54,9 +54,10 @@ public class SynchronizeService extends JobIntentService { private static final String claimResponseLine = "[%s] %s"; - private Global global; - private SQLHandler sqlHandler; - private StorageManager storageManager; + protected Global global; + protected SQLHandler sqlHandler; + protected StorageManager storageManager; + protected PostNewClaims postNewClaims; @Override public void onCreate() { @@ -66,6 +67,10 @@ public void onCreate() { storageManager = StorageManager.of(this); } + public void setPostNewClaims(PostNewClaims postNewClaims) { + this.postNewClaims = postNewClaims; + } + public static void uploadClaims(Context context) { Intent intent = new Intent(); intent.setAction(ACTION_UPLOAD_CLAIMS); @@ -96,7 +101,7 @@ protected void onHandleWork(@NonNull Intent intent) { } } - private void handleUploadClaims() { + protected void handleUploadClaims() { if (!global.isNetworkAvailable()) { broadcastError(getResources().getString(R.string.CheckInternet), ACTION_UPLOAD_CLAIMS); return; @@ -109,7 +114,10 @@ private void handleUploadClaims() { } try { - List results = new PostNewClaims().execute(PendingClaim.fromJson(claims)); + if (postNewClaims == null) { + postNewClaims = new PostNewClaims(); + } + List results = postNewClaims.execute(PendingClaim.fromJson(claims)); JSONArray claimStatus = processClaimResponse(results); broadcastSyncSuccess(claimStatus); } catch (Exception e) { @@ -118,7 +126,7 @@ private void handleUploadClaims() { } } - private JSONArray processClaimResponse(List results) { + protected JSONArray processClaimResponse(List results) { JSONArray jsonResults = new JSONArray(); String date = AppInformation.DateTimeInfo.getDefaultIsoDatetimeFormatter().format(new Date()); for (PostNewClaims.Result result : results) { @@ -252,7 +260,7 @@ private Uri createClaimExportZip(ArrayList exportedClaims) { zipFile); } - private void handleGetClaimCount() { + protected void handleGetClaimCount() { JSONObject counts = sqlHandler.getClaimCounts(); int enteredCount = counts.optInt(SQLHandler.CLAIM_UPLOAD_STATUS_ENTERED, 0); diff --git a/claimManagement/src/test/java/org/openimis/imisclaims/ClaimActivityTest.java b/claimManagement/src/test/java/org/openimis/imisclaims/ClaimActivityTest.java new file mode 100644 index 00000000..f6a90b1d --- /dev/null +++ b/claimManagement/src/test/java/org/openimis/imisclaims/ClaimActivityTest.java @@ -0,0 +1,297 @@ +package org.openimis.imisclaims; +import org.openimis.imisclaims.domain.entity.Claim; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import android.content.ContentValues; +import android.text.SpannableStringBuilder; +import android.view.View; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Date; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class ClaimActivityTest { + + ClaimActivity activity; + + @Before + public void setup() { + MockitoAnnotations.openMocks(this); + + activity = Robolectric.buildActivity(ClaimActivity.class) + .create() + .start() + .resume() + .get(); + + // Inject mocks + activity.sqlHandler = mock(SQLHandler.class); + activity.global = mock(Global.class); + + when(activity.global.isNetworkAvailable()).thenReturn(true); + when(activity.sqlHandler.getAdjustability(anyString())).thenReturn("M"); + + // initialize static lists + ClaimActivity.lvItemList = new ArrayList<>(); + ClaimActivity.lvServiceList = new ArrayList<>(); + + // set mandatory fields + activity.etHealthFacility.setText("HF001"); + activity.etClaimAdmin.setText("ADMIN001"); + activity.etClaimCode.setText("CLM001"); + activity.etInsureeNumber.setText("CHF12345"); + activity.etStartDate.setText("2025-01-01"); + activity.etEndDate.setText("2025-01-02"); + activity.etDiagnosis.setText("A01"); + + activity.etVisitType.setText("Other"); + activity.etVisitType.setTag("O"); + + activity.etPatientCondition.setText("Healed"); + activity.etPatientCondition.setTag("H"); + + activity.tvItemTotal.setText("1"); + activity.tvServiceTotal.setText("0"); + + // add fake items and services to avoid MissingClaim + ArrayList> fakeItems = new ArrayList<>(); + HashMap item1 = new HashMap<>(); + item1.put("Code", "ITEM001"); + item1.put("Price", "50"); + item1.put("Quantity", "1"); + fakeItems.add(item1); + ClaimActivity.lvItemList = fakeItems; + + ArrayList> fakeServices = new ArrayList<>(); + HashMap svc1 = new HashMap<>(); + svc1.put("Code", "SVC001"); + svc1.put("Price", "40"); + svc1.put("Quantity", "1"); + svc1.put("PackageType", "P"); + svc1.put("SubServicesItems", "[]"); + fakeServices.add(svc1); + ClaimActivity.lvServiceList = fakeServices; + } + + /* ===================================================== + isValidData() + ===================================================== */ + + @Test + public void isValidData_AllValid_ReturnsTrue() { + boolean result = activity.isValidData(); + assertTrue(result); + } + + @Test + public void isValidData_MissingHealthFacility_ReturnsFalse() { + activity.etHealthFacility.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingClaimAdmin_WhenMandatory_ReturnsFalse() { + when(activity.sqlHandler.getAdjustability("ClaimAdministrator")) + .thenReturn("M"); + + activity.etClaimAdmin.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingClaimCode_ReturnsFalse() { + activity.etClaimCode.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingInsureeNumber_ReturnsFalse() { + activity.etInsureeNumber.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_InvalidInsureeNumber_ReturnsFalse() { + activity.etInsureeNumber.setText(""); + Escape escape = mock(Escape.class); + when(escape.CheckCHFID(anyString())).thenReturn(false); // Mock Escape.CheckCHFID to return false + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingStartDate_ReturnsFalse() { + activity.etStartDate.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingEndDate_ReturnsFalse() { + activity.etEndDate.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingDiagnosis_ReturnsFalse() { + activity.etDiagnosis.setText(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_MissingVisitType_ReturnsFalse() { + activity.etVisitType.setText(""); + activity.etVisitType.setTag(""); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + @Test + public void isValidData_NoItemsAndServices_ReturnsFalse() { + ClaimActivity.lvItemList.clear(); + ClaimActivity.lvServiceList.clear(); + activity.tvItemTotal.setText("0"); + activity.tvServiceTotal.setText("0"); + + boolean result = activity.isValidData(); + + assertFalse(result); + } + + /* ===================================================== + saveClaim() + ===================================================== */ + + @Test + public void saveClaim_ValidData_CallsSqlHandlerAndReturnsTrue() { + doNothing().when(activity.sqlHandler) + .saveClaim(any(ContentValues.class), anyList(), anyList()); + + boolean result = activity.saveClaim(); + + assertTrue(result); + verify(activity.sqlHandler, times(1)) + .saveClaim(any(ContentValues.class), anyList(), anyList()); + } + + @Test + public void saveClaim_ContentValuesContainExpectedData() { + doNothing().when(activity.sqlHandler) + .saveClaim(any(ContentValues.class), anyList(), anyList()); + + activity.saveClaim(); + + verify(activity.sqlHandler).saveClaim( + argThat(cv -> + cv.getAsString("HFCode").equals("HF001") && + cv.getAsString("ClaimCode").equals("CLM001") && + cv.getAsString("VisitType").equals("O") && + cv.getAsInteger("PreAuthorization") == 0 + ), + anyList(), + anyList() + ); + } + + /* ===================================================== + fillClaimFromRestore() + ===================================================== */ + + @Test + public void fillClaimFromRestore_FillsAllFieldsCorrectly() throws Exception { + // Build a complete claim + Claim.Medication med = new Claim.Medication( + "MED1", "Paracetamol", 50.0, "USD", "2", null, null, null, null, null + ); + + Claim.Service svc = new Claim.Service( + "SVC1", "Consultation", 100.0, "USD", "1", null, null, null, null, null + ); + + Claim claim = new Claim( + "UUID123", + "HF001", + "Health Facility", + "INS001", + "John Doe", + "CLM123", + new Date(), + new Date(), + new Date(), + "E", + Claim.Status.ENTERED, + "A01", + "B02", + null, + null, + null, + 150.0, + 150.0, + null, + null, + "G001", + List.of(svc), + List.of(med) + ); + + // Mock global for the method + when(activity.global.getOfficerCode()).thenReturn("ADMIN001"); + when(activity.global.getOfficerHealthFacility()).thenReturn("HF001"); + + // Call the private method using reflection + java.lang.reflect.Method method = ClaimActivity.class + .getDeclaredMethod("fillClaimFromRestore", Claim.class); + method.setAccessible(true); + method.invoke(activity, claim); + + // Verify that UI fields were filled correctly + assertEquals("@CLM123", activity.etClaimCode.getText().toString()); // @ is the mocks resource string to replace "Restored" + assertEquals("ADMIN001", activity.etClaimAdmin.getText().toString()); + assertEquals("HF001", activity.etHealthFacility.getText().toString()); + assertEquals("G001", activity.etGuaranteeNo.getText().toString()); + assertEquals("", activity.etInsureeNumber.getText().toString()); // because Status != REJECTED + assertEquals("", activity.etDiagnosis.getText().toString()); + + // Verify that the lists were populated + assertEquals(1, ClaimActivity.lvItemList.size()); + assertEquals(1, ClaimActivity.lvServiceList.size()); + assertEquals(2, activity.TotalItemService); // 1 item + 1 service + } + +} diff --git a/claimManagement/src/test/java/org/openimis/imisclaims/ClaimManagementActivityTest.java b/claimManagement/src/test/java/org/openimis/imisclaims/ClaimManagementActivityTest.java deleted file mode 100644 index 31b92010..00000000 --- a/claimManagement/src/test/java/org/openimis/imisclaims/ClaimManagementActivityTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.openimis.imisclaims; - -import junit.framework.TestCase; - -public class ClaimManagementActivityTest extends TestCase { - -} \ No newline at end of file diff --git a/claimManagement/src/test/java/org/openimis/imisclaims/SynchronizeServiceTest.java b/claimManagement/src/test/java/org/openimis/imisclaims/SynchronizeServiceTest.java new file mode 100644 index 00000000..1d003649 --- /dev/null +++ b/claimManagement/src/test/java/org/openimis/imisclaims/SynchronizeServiceTest.java @@ -0,0 +1,285 @@ +package org.openimis.imisclaims; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openimis.imisclaims.domain.entity.Claim; +import org.openimis.imisclaims.usecase.FetchClaims; +import java.util.List; +import java.util.Arrays; +import java.util.Date; + + +import org.openimis.imisclaims.usecase.PostNewClaims; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import org.openimis.imisclaims.tools.StorageManager; + +@RunWith(RobolectricTestRunner.class) +public class SynchronizeServiceTest { + + @Mock private Global global; + @Mock private SQLHandler sqlHandler; + @Mock private Resources resources; + @Mock private Context context; + @Mock private StorageManager storageManager; + + private SynchronizeService synchronizeService; + + @Before + public void setUp() { + MockitoAnnotations.openMocks(this); + + synchronizeService = new SynchronizeService() { + @Override + public Context getApplicationContext() { + return context; + } + + @Override + public Resources getResources() { + return resources; + } + + @Override + public void sendBroadcast(Intent intent) { + // override to avoid real broadcast and capture intents if needed + capturedIntent = intent; + } + }; + + synchronizeService.global = global; + synchronizeService.sqlHandler = sqlHandler; + synchronizeService.storageManager = storageManager; + + when(context.getResources()).thenReturn(resources); + when(resources.getString(anyInt())).thenReturn("Error message"); + } + + private Intent capturedIntent; + + // ---------------------------------- + // Tests handleUploadClaims + // ---------------------------------- + + @Test + public void handleUploadClaims_WhenNoNetwork_BroadcastsError() { + when(global.isNetworkAvailable()).thenReturn(false); + + synchronizeService.handleUploadClaims(); + + verify(global).isNetworkAvailable(); + assertNotNull(capturedIntent); + assertEquals(SynchronizeService.ACTION_SYNC_ERROR, capturedIntent.getAction()); + System.out.println("Error Message: " + capturedIntent.getStringExtra(SynchronizeService.EXTRA_ERROR_MESSAGE)); + assertEquals("Error message", capturedIntent.getStringExtra(SynchronizeService.EXTRA_ERROR_MESSAGE)); + } + + @Test + public void handleUploadClaims_WhenNoPendingClaims_BroadcastsNoClaimError() throws JSONException { + when(global.isNetworkAvailable()).thenReturn(true); + when(sqlHandler.getAllPendingClaims()).thenReturn(new JSONArray()); + + synchronizeService.handleUploadClaims(); + + verify(sqlHandler).getAllPendingClaims(); + assertNotNull(capturedIntent); + assertEquals(SynchronizeService.ACTION_SYNC_ERROR, capturedIntent.getAction()); + assertEquals("Error message", capturedIntent.getStringExtra(SynchronizeService.EXTRA_ERROR_MESSAGE)); + } + + // Note : we can't test PostNewClaims here without refactoring + // We just test that the method doesn't crash with pending claims + @Test + public void handleUploadClaims_WithPendingClaims_DoesNotCrash() throws JSONException { + when(global.isNetworkAvailable()).thenReturn(true); + + JSONArray pendingClaims = new JSONArray(); + JSONObject claim = new JSONObject(); + claim.put("id", "claim123"); + pendingClaims.put(claim); + + when(sqlHandler.getAllPendingClaims()).thenReturn(pendingClaims); + + synchronizeService.handleUploadClaims(); + + verify(sqlHandler).getAllPendingClaims(); + } + + // ---------------------------------- + // Tests processClaimResponse + // ---------------------------------- + + @Test + public void processClaimResponse_WithRejectedClaim_UpdatesStatusToRejected() throws JSONException { + PostNewClaims.Result rejectedResult = + new PostNewClaims.Result("claim123", PostNewClaims.Result.Status.REJECTED, "Claim rejected"); + + when(sqlHandler.getClaimUUIDForCode("claim123")).thenReturn("uuid123"); + + JSONArray result = synchronizeService.processClaimResponse(Arrays.asList(rejectedResult)); + + verify(sqlHandler).insertClaimUploadStatus( + eq("uuid123"), + anyString(), + eq(SQLHandler.CLAIM_UPLOAD_STATUS_REJECTED), + isNull() + ); + + assertEquals(1, result.length()); + assertTrue(result.getString(0).contains("Claim rejected")); + } + + @Test + public void processClaimResponse_WithError_UpdatesStatusToError() throws JSONException { + PostNewClaims.Result errorResult = + new PostNewClaims.Result("claim123", PostNewClaims.Result.Status.ERROR, "Server error"); + + when(sqlHandler.getClaimUUIDForCode("claim123")).thenReturn("uuid123"); + + JSONArray result = synchronizeService.processClaimResponse(Arrays.asList(errorResult)); + + verify(sqlHandler).insertClaimUploadStatus( + eq("uuid123"), + anyString(), + eq(SQLHandler.CLAIM_UPLOAD_STATUS_ERROR), + eq("Server error") + ); + + assertEquals(1, result.length()); + } + + @Test + public void processClaimResponse_WithSuccess_UpdatesStatusToAccepted() throws JSONException { + PostNewClaims.Result successResult = + new PostNewClaims.Result("claim123", PostNewClaims.Result.Status.SUCCESS, null); + + when(sqlHandler.getClaimUUIDForCode("claim123")).thenReturn("uuid123"); + + JSONArray result = synchronizeService.processClaimResponse(Arrays.asList(successResult)); + + verify(sqlHandler).insertClaimUploadStatus( + eq("uuid123"), + anyString(), + eq(SQLHandler.CLAIM_UPLOAD_STATUS_ACCEPTED), + isNull() + ); + + assertEquals(0, result.length()); // no error message for SUCCESS + } + + // ---------------------------------- + // Test handleGetClaimCount + // ---------------------------------- + + @Test + public void handleGetClaimCount_BroadcastsCorrectCounts() throws JSONException { + JSONObject counts = new JSONObject(); + counts.put(SQLHandler.CLAIM_UPLOAD_STATUS_ENTERED, 5); + counts.put(SQLHandler.CLAIM_UPLOAD_STATUS_ACCEPTED, 3); + counts.put(SQLHandler.CLAIM_UPLOAD_STATUS_REJECTED, 2); + + when(sqlHandler.getClaimCounts()).thenReturn(counts); + + synchronizeService.handleGetClaimCount(); + + assertNotNull(capturedIntent); + assertEquals(SynchronizeService.ACTION_CLAIM_COUNT_RESULT, capturedIntent.getAction()); + assertEquals(5, capturedIntent.getIntExtra(SynchronizeService.EXTRA_CLAIM_COUNT_ENTERED, 0)); + assertEquals(3, capturedIntent.getIntExtra(SynchronizeService.EXTRA_CLAIM_COUNT_ACCEPTED, 0)); + assertEquals(2, capturedIntent.getIntExtra(SynchronizeService.EXTRA_CLAIM_COUNT_REJECTED, 0)); + } + + @Test + public void testDownloadClaims_WhenNetworkAvailable_ReturnsClaimsList() throws Exception { + // Given + when(global.isNetworkAvailable()).thenReturn(true); + + // Create a mock claim + Claim.Service mockService = new Claim.Service( + "SERVICE1", "Service 1", 100.0, "$", + "1", "1", null, null, null, null); + Claim.Medication mockMedication = new Claim.Medication( + "MED1", "Medication 1", 50.0, "$", + "2", "2", null, null, null, null); + + Claim mockClaim = new Claim( + "claim-uuid-123", "HF001", "Health Facility 1", + "INS123", "John Doe", "CLAIM-001", + new Date(), new Date(), new Date(), + "O", Claim.Status.PROCESSED, "A01", + null, null, null, null, + 150.0, 150.0, null, null, "G123", + Arrays.asList(mockService), + Arrays.asList(mockMedication) + ); + + // Mock the FetchClaims class + FetchClaims fetchClaims = mock(FetchClaims.class); + when(fetchClaims.execute( + eq(global.getOfficerCode()), + any(Claim.Status.class), + any(Date.class), + any(Date.class), + any(Date.class), + any(Date.class) + )).thenReturn(Arrays.asList(mockClaim)); + + // When + List claims = fetchClaims.execute( + global.getOfficerCode(), + Claim.Status.PROCESSED, + new Date(), + new Date(), + new Date(), + new Date() + ); + + // Then + assertNotNull(claims); + assertFalse(claims.isEmpty()); + assertEquals(1, claims.size()); + assertEquals("CLAIM-001", claims.get(0).getClaimNumber()); + assertEquals("John Doe", claims.get(0).getPatientName()); + assertEquals(Claim.Status.PROCESSED, claims.get(0).getStatus()); + + // Verify the service and medication were included + assertFalse(claims.get(0).getServices().isEmpty()); + assertFalse(claims.get(0).getMedications().isEmpty()); + assertEquals("SERVICE1", claims.get(0).getServices().get(0).getCode()); + assertEquals("MED1", claims.get(0).getMedications().get(0).getCode()); + } + + @Test + public void testDownloadClaims_WhenNetworkUnavailable_ThrowsException() { + // Given + when(global.isNetworkAvailable()).thenReturn(false); + + // When/Then + assertThrows(Exception.class, () -> { + // This should fail because there's no network + new FetchClaims().execute( + global.getOfficerCode(), + Claim.Status.PROCESSED, + new Date(), + new Date(), + new Date(), + new Date() + ); + }); + } +} diff --git a/gradle.properties b/gradle.properties index 5465fec0..dbb7bf70 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true