From ae49bd92f01e94fb8824d854c0fe8c603d024fdc Mon Sep 17 00:00:00 2001 From: Ben Hesford Date: Tue, 19 Nov 2024 15:18:20 -0700 Subject: [PATCH 1/3] WIP --- .../processor/coverage/CoverageDriverImpl.java | 17 +++++++++++------ .../coverage/CoverageDriverUnitTest.java | 11 ++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java index 78810ac47..2204f32af 100644 --- a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java +++ b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java @@ -555,29 +555,34 @@ public int numberOfBeneficiariesToProcess(Job job, ContractDTO contract) { @Trace(metricName = "EnrollmentLoadFromDB", dispatcher = true) @Override public CoveragePagingResult pageCoverage(Job job, ContractDTO contract) { - ZonedDateTime now = getEndDateTime(); if (contract == null) { throw new CoverageDriverException("cannot retrieve metadata for job missing contract"); } - ZonedDateTime startDateTime = getStartDateTime(contract); - + Optional additionalDetails = Optional.empty(); try { + ZonedDateTime now = getEndDateTime(); + ZonedDateTime startDateTime = getStartDateTime(contract); // Check that all coverage periods necessary are present before beginning to page while (startDateTime.isBefore(now)) { + additionalDetails = Optional.of(String.format("contract='%s' month='%s', year='%s'", + contract.getContractNumber(), + startDateTime.getMonthValue(), + startDateTime.getYear())); // Will throw exception if it doesn't exist coverageService.getCoveragePeriod(mapping.map(contract), startDateTime.getMonthValue(), startDateTime.getYear()); startDateTime = startDateTime.plusMonths(1); } + additionalDetails = Optional.empty(); // Make initial request which returns a result and a request starting at the next cursor CoveragePagingRequest request = new CoveragePagingRequest(PAGING_SIZE, null, mapping.map(contract), job.getCreatedAt()); - + additionalDetails = Optional.of(request.toString()); // Make request for coverage metadata return coverageService.pageCoverage(request); } catch (Exception exception) { - log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier"); + log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier - {}", additionalDetails.orElse("")); throw new CoverageDriverException("coverage driver failing preconditions", exception); } } @@ -632,7 +637,7 @@ public CoveragePagingResult pageCoverage(CoveragePagingRequest request) { try { return coverageService.pageCoverage(request); } catch (Exception exception) { - log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier"); + log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier - {}", request.toString()); throw new CoverageDriverException("coverage driver failing preconditions", exception); } } diff --git a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java index 2e8d81264..1d87ea4e4 100644 --- a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java +++ b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java @@ -27,6 +27,7 @@ import javax.persistence.EntityNotFoundException; import gov.cms.ab2d.worker.service.coveragesnapshot.CoverageSnapshotService; +import lombok.val; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +37,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.test.util.ReflectionTestUtils; @@ -60,7 +63,7 @@ /** * Tests for paging coverage which are much easier using mocked resources */ -@ExtendWith(MockitoExtension.class) +@ExtendWith({MockitoExtension.class, OutputCaptureExtension.class}) class CoverageDriverUnitTest { @Mock @@ -354,7 +357,7 @@ void failureToLockCoverageAvailableFailsQuietly() { @DisplayName("When paging coverage fails throw coverage driver exception") @Test - void failureToPageCausesExceptions() { + void failureToPageCausesExceptions(CapturedOutput output) { when(coverageService.pageCoverage(any())).thenThrow(RuntimeException.class); CoverageDriver driver = new CoverageDriverImpl(null, null, coverageService, null, null, null,null, snapshotService); @@ -362,8 +365,10 @@ void failureToPageCausesExceptions() { ContractForCoverageDTO contract = new ContractForCoverageDTO(); contract.setContractNumber("contractNum"); - CoverageDriverException exception = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(new CoveragePagingRequest( 1000, null, contract, OffsetDateTime.now()))); + val coveragePagingRequest = new CoveragePagingRequest( 1000, null, contract, OffsetDateTime.now()); + CoverageDriverException exception = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(coveragePagingRequest)); assertTrue(exception.getMessage().contains("coverage driver failing preconditions")); + assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - " + coveragePagingRequest.toString())); } @DisplayName("When loading a mapping job exit early if conditions not met") From 6073972f91bf68a3720281e0ee4d1fa4d6a8877b Mon Sep 17 00:00:00 2001 From: Ben Hesford Date: Tue, 19 Nov 2024 15:34:51 -0700 Subject: [PATCH 2/3] Add unit tests --- .../ab2d/worker/processor/coverage/CoverageDriverImpl.java | 4 ++-- .../worker/processor/coverage/CoverageDriverUnitTest.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java index 2204f32af..78718b53a 100644 --- a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java +++ b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java @@ -555,15 +555,15 @@ public int numberOfBeneficiariesToProcess(Job job, ContractDTO contract) { @Trace(metricName = "EnrollmentLoadFromDB", dispatcher = true) @Override public CoveragePagingResult pageCoverage(Job job, ContractDTO contract) { + ZonedDateTime now = getEndDateTime(); if (contract == null) { throw new CoverageDriverException("cannot retrieve metadata for job missing contract"); } + ZonedDateTime startDateTime = getStartDateTime(contract); Optional additionalDetails = Optional.empty(); try { - ZonedDateTime now = getEndDateTime(); - ZonedDateTime startDateTime = getStartDateTime(contract); // Check that all coverage periods necessary are present before beginning to page while (startDateTime.isBefore(now)) { additionalDetails = Optional.of(String.format("contract='%s' month='%s', year='%s'", diff --git a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java index 1d87ea4e4..2e9beb475 100644 --- a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java +++ b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java @@ -234,7 +234,7 @@ void pageRequestWhenSinceDateAfterNow() { @DisplayName("Paging coverage fails when coverage periods are missing") @Test - void failPagingWhenCoveragePeriodMissing() { + void failPagingWhenCoveragePeriodMissing(CapturedOutput output) { when(coverageService.getCoveragePeriod(any(), anyInt(), anyInt())).thenThrow(new EntityNotFoundException()); @@ -243,6 +243,8 @@ void failPagingWhenCoveragePeriodMissing() { CoverageDriverException startDateInFuture = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(job, contract)); assertEquals(EntityNotFoundException.class, startDateInFuture.getCause().getClass()); + assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - contract='null' month='1', year='2020'")); + } @DisplayName("Paging coverage periods") From f8b30b819e142c6901118f5438d74e39be59bb7f Mon Sep 17 00:00:00 2001 From: Ben Hesford Date: Tue, 19 Nov 2024 16:31:09 -0700 Subject: [PATCH 3/3] Update tests, add comment --- .../coverage/CoverageDriverImpl.java | 1 + .../coverage/CoverageDriverUnitTest.java | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java index 78718b53a..98047fbe1 100644 --- a/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java +++ b/worker/src/main/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverImpl.java @@ -562,6 +562,7 @@ public CoveragePagingResult pageCoverage(Job job, ContractDTO contract) { } ZonedDateTime startDateTime = getStartDateTime(contract); + // Additional details to log in the event of exception Optional additionalDetails = Optional.empty(); try { // Check that all coverage periods necessary are present before beginning to page diff --git a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java index 2e9beb475..d13c670a0 100644 --- a/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java +++ b/worker/src/test/java/gov/cms/ab2d/worker/processor/coverage/CoverageDriverUnitTest.java @@ -232,6 +232,27 @@ void pageRequestWhenSinceDateAfterNow() { assertNotNull(result); } + @DisplayName("Paging coverage fails when all coverage periods are present but CoverageService#pageCoverage throws exception") + @Test + void failPagingWhenCoveragePeriodsPresentButUnderlyingMethodThrowsException(CapturedOutput output) { + when(coverageService.getCoveragePeriod(any(ContractForCoverageDTO.class), anyInt(), anyInt())).thenAnswer((invocationOnMock) -> { + CoveragePeriod period = new CoveragePeriod(); + period.setContractNumber((invocationOnMock.getArgument(0).toString())); + period.setMonth(invocationOnMock.getArgument(1)); + period.setYear(invocationOnMock.getArgument(2)); + return period; + }); + + when(coverageService.pageCoverage(any())).thenThrow(RuntimeException.class); + + Job job = new Job(); + ContractDTO contract = new ContractDTO(null, "Contract-0", null, AB2D_EPOCH.toOffsetDateTime(), null, 0, 0); + when(mapping.map(any(ContractDTO.class))).thenReturn(new ContractForCoverageDTO("Contract-0", contract.getAttestedOn(), ContractForCoverageDTO.ContractType.NORMAL)); + + assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(job, contract)); + assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - CoveragePagingRequest(jobStartTime=null, contract=ContractForCoverageDTO(contractNumber=Contract-0, attestedOn=2020-01-01T00:00-05:00, contractType=NORMAL), pageSize=10000, cursor=Optional.empty)")); + } + @DisplayName("Paging coverage fails when coverage periods are missing") @Test void failPagingWhenCoveragePeriodMissing(CapturedOutput output) { @@ -244,7 +265,6 @@ void failPagingWhenCoveragePeriodMissing(CapturedOutput output) { CoverageDriverException startDateInFuture = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(job, contract)); assertEquals(EntityNotFoundException.class, startDateInFuture.getCause().getClass()); assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - contract='null' month='1', year='2020'")); - } @DisplayName("Paging coverage periods") @@ -367,10 +387,10 @@ void failureToPageCausesExceptions(CapturedOutput output) { ContractForCoverageDTO contract = new ContractForCoverageDTO(); contract.setContractNumber("contractNum"); - val coveragePagingRequest = new CoveragePagingRequest( 1000, null, contract, OffsetDateTime.now()); + val coveragePagingRequest = new CoveragePagingRequest( 1000, null, contract, AB2D_EPOCH.toOffsetDateTime()); CoverageDriverException exception = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(coveragePagingRequest)); assertTrue(exception.getMessage().contains("coverage driver failing preconditions")); - assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - " + coveragePagingRequest.toString())); + assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - CoveragePagingRequest(jobStartTime=2020-01-01T00:00-05:00, contract=ContractForCoverageDTO(contractNumber=contractNum, attestedOn=null, contractType=null), pageSize=1000, cursor=Optional.empty")); } @DisplayName("When loading a mapping job exit early if conditions not met")