From 8533fb8133e8ca816b7ba5309936fe67080f2d4e Mon Sep 17 00:00:00 2001 From: Basilio Bogado <541149+basiliskus@users.noreply.github.com> Date: Mon, 12 Feb 2024 09:22:01 -0800 Subject: [PATCH] Implementation to send the FHIR result to RS Waters endpoint (#859) * Refactored to extract common code into helper function and implemented send method for results * Added methods for results and order sender * Fixed typo * Updated tests to reflect new changes * Moved ReportStreamSenderHelper resgistration * Added java docs * Added test coverage * Improved assertions for test --- .../etor/EtorDomainRegistration.java | 3 + .../reportstream/ReportStreamOrderSender.java | 50 +------ .../ReportStreamResultSender.java | 12 +- .../ReportStreamSenderHelper.java | 78 ++++++++++ .../cdc/trustedintermediary/ResultMock.groovy | 4 +- .../ReportStreamOrderSenderTest.groovy | 108 +------------- .../ReportStreamResultSenderTest.groovy | 18 ++- .../ReportStreamSenderHelperTest.groovy | 137 ++++++++++++++++++ 8 files changed, 259 insertions(+), 151 deletions(-) create mode 100644 etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelper.java create mode 100644 etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelperTest.groovy diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java index 05c2f88b2..02784bc95 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java @@ -37,6 +37,7 @@ import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamEndpointClient; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamOrderSender; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamResultSender; +import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamSenderHelper; import gov.hhs.cdc.trustedintermediary.wrappers.FhirParseException; import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; @@ -104,6 +105,8 @@ public Map> domainRegistra ApplicationContext.register(ResultSender.class, ReportStreamResultSender.getInstance()); ApplicationContext.register(ResultController.class, ResultController.getInstance()); ApplicationContext.register(SendResultUseCase.class, SendResultUseCase.getInstance()); + ApplicationContext.register( + ReportStreamSenderHelper.class, ReportStreamSenderHelper.getInstance()); if (ApplicationContext.getProperty("DB_URL") != null) { ApplicationContext.register(DbDao.class, PostgresDao.getInstance()); diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSender.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSender.java index c4cb0872a..63b20bd3d 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSender.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSender.java @@ -1,17 +1,10 @@ package gov.hhs.cdc.trustedintermediary.external.reportstream; -import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient; import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException; -import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep; import gov.hhs.cdc.trustedintermediary.etor.orders.Order; import gov.hhs.cdc.trustedintermediary.etor.orders.OrderSender; import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; -import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata; -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter; -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException; -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference; -import java.util.Map; import java.util.Optional; import javax.inject.Inject; @@ -20,11 +13,9 @@ public class ReportStreamOrderSender implements OrderSender { private static final ReportStreamOrderSender INSTANCE = new ReportStreamOrderSender(); - @Inject private RSEndpointClient rsclient; - @Inject private Formatter formatter; - @Inject private HapiFhir fhir; - @Inject private Logger logger; - @Inject MetricMetadata metadata; + @Inject ReportStreamSenderHelper sender; + @Inject HapiFhir fhir; + @Inject Logger logger; public static ReportStreamOrderSender getInstance() { return INSTANCE; @@ -35,40 +26,7 @@ private ReportStreamOrderSender() {} @Override public Optional send(final Order order) throws UnableToSendMessageException { logger.logInfo("Sending the order to ReportStream"); - String json = fhir.encodeResourceToJson(order.getUnderlyingOrder()); - String bearerToken; - String rsResponseBody; - - try { - bearerToken = rsclient.getRsToken(); - rsResponseBody = rsclient.requestWatersEndpoint(json, bearerToken); - } catch (ReportStreamEndpointClientException e) { - throw new UnableToSendMessageException("Unable to send order to ReportStream", e); - } - - logger.logInfo("Order successfully sent to ReportStream"); - metadata.put(order.getFhirResourceId(), EtorMetadataStep.SENT_TO_REPORT_STREAM); - - Optional sentSubmissionId = getSubmissionId(rsResponseBody); - if (sentSubmissionId.isEmpty()) { - logger.logError("Unable to retrieve sentSubmissionId from ReportStream response"); - } else { - logger.logInfo("ReportStream response's sentSubmissionId={}", sentSubmissionId); - } - - return sentSubmissionId; - } - - protected Optional getSubmissionId(String rsResponseBody) { - try { - Map rsResponse = - formatter.convertJsonToObject(rsResponseBody, new TypeReference<>() {}); - return Optional.ofNullable(rsResponse.get("submissionId").toString()); - } catch (FormatterProcessingException e) { - logger.logError("Unable to get the submissionId", e); - } - - return Optional.empty(); + return sender.sendOrderToReportStream(json, order.getFhirResourceId()); } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSender.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSender.java index 1a6869838..38b22c452 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSender.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSender.java @@ -3,7 +3,10 @@ import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException; import gov.hhs.cdc.trustedintermediary.etor.results.Result; import gov.hhs.cdc.trustedintermediary.etor.results.ResultSender; +import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir; +import gov.hhs.cdc.trustedintermediary.wrappers.Logger; import java.util.Optional; +import javax.inject.Inject; /** * This class is responsible for sending results to the ReportStream service and receiving a @@ -13,6 +16,10 @@ public class ReportStreamResultSender implements ResultSender { private static final ReportStreamResultSender INSTANCE = new ReportStreamResultSender(); + @Inject ReportStreamSenderHelper sender; + @Inject HapiFhir fhir; + @Inject Logger logger; + public static ReportStreamResultSender getInstance() { return INSTANCE; } @@ -21,7 +28,8 @@ private ReportStreamResultSender() {} @Override public Optional send(Result result) throws UnableToSendMessageException { - // todo: implement in #616 - return Optional.empty(); + logger.logInfo("Sending results to ReportStream"); + String json = fhir.encodeResourceToJson(result.getUnderlyingResult()); + return sender.sendResultToReportStream(json, result.getFhirResourceId()); } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelper.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelper.java new file mode 100644 index 000000000..cf2598374 --- /dev/null +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelper.java @@ -0,0 +1,78 @@ +package gov.hhs.cdc.trustedintermediary.external.reportstream; + +import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient; +import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException; +import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep; +import gov.hhs.cdc.trustedintermediary.wrappers.Logger; +import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference; +import java.util.Map; +import java.util.Optional; +import javax.inject.Inject; + +/** Helper class for sending messages to ReportStream */ +public class ReportStreamSenderHelper { + private static final ReportStreamSenderHelper INSTANCE = new ReportStreamSenderHelper(); + + @Inject RSEndpointClient rsclient; + @Inject Formatter formatter; + @Inject Logger logger; + @Inject MetricMetadata metadata; + + private ReportStreamSenderHelper() {} + + public static ReportStreamSenderHelper getInstance() { + return INSTANCE; + } + + public Optional sendOrderToReportStream(String body, String fhirResourceId) + throws UnableToSendMessageException { + return sendToReportStream(body, fhirResourceId, "order"); + } + + public Optional sendResultToReportStream(String body, String fhirResourceId) + throws UnableToSendMessageException { + return sendToReportStream(body, fhirResourceId, "result"); + } + + protected Optional sendToReportStream( + String body, String fhirResourceId, String messageType) + throws UnableToSendMessageException { + String bearerToken; + String rsResponseBody; + + try { + bearerToken = rsclient.getRsToken(); + rsResponseBody = rsclient.requestWatersEndpoint(body, bearerToken); + } catch (ReportStreamEndpointClientException e) { + throw new UnableToSendMessageException( + "Unable to send " + messageType + " to ReportStream", e); + } + + logger.logInfo("{} successfully sent to ReportStream", messageType); + metadata.put(fhirResourceId, EtorMetadataStep.SENT_TO_REPORT_STREAM); + + Optional sentSubmissionId = getSubmissionId(rsResponseBody); + if (sentSubmissionId.isEmpty()) { + logger.logError("Unable to retrieve sentSubmissionId from ReportStream response"); + } else { + logger.logInfo("ReportStream response's sentSubmissionId={}", sentSubmissionId); + } + + return sentSubmissionId; + } + + protected Optional getSubmissionId(String rsResponseBody) { + try { + Map rsResponse = + formatter.convertJsonToObject(rsResponseBody, new TypeReference<>() {}); + return Optional.ofNullable(rsResponse.get("submissionId").toString()); + } catch (FormatterProcessingException e) { + logger.logError("Unable to get the submissionId", e); + } + + return Optional.empty(); + } +} diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/ResultMock.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/ResultMock.groovy index af190ff07..d925f02f3 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/ResultMock.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/ResultMock.groovy @@ -10,9 +10,9 @@ class ResultMock implements Result { private String fhirResourceId private T underlyingResult - ResultMock(String fhirResourceId, T underlyingOrders) { + ResultMock(String fhirResourceId, T underlyingResult) { this.fhirResourceId = fhirResourceId - this.underlyingResult = underlyingOrders + this.underlyingResult = underlyingResult } @Override diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSenderTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSenderTest.groovy index 06018d1e5..803fdf685 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSenderTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamOrderSenderTest.groovy @@ -3,20 +3,10 @@ package gov.hhs.cdc.trustedintermediary.external.reportstream import gov.hhs.cdc.trustedintermediary.OrderMock import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient -import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep import gov.hhs.cdc.trustedintermediary.etor.orders.OrderSender -import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson import gov.hhs.cdc.trustedintermediary.external.localfile.MockRSEndpointClient -import gov.hhs.cdc.trustedintermediary.wrappers.AuthEngine -import gov.hhs.cdc.trustedintermediary.wrappers.Cache import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir -import gov.hhs.cdc.trustedintermediary.wrappers.HttpClient -import gov.hhs.cdc.trustedintermediary.wrappers.Logger import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata -import gov.hhs.cdc.trustedintermediary.wrappers.Secrets -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException -import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference import spock.lang.Specification class ReportStreamOrderSenderTest extends Specification { @@ -31,106 +21,24 @@ class ReportStreamOrderSenderTest extends Specification { def "send order works"() { given: - def mockAuthEngine = Mock(AuthEngine) - TestApplicationContext.register(AuthEngine, mockAuthEngine) + def fhirResourceId = null + def underlyingOrder = "Mock order" + def mockOrder = new OrderMock(fhirResourceId, "patient-id", underlyingOrder) - def mockSecrets = Mock(Secrets) - TestApplicationContext.register(Secrets, mockSecrets) - - def mockClient = Mock(HttpClient) - mockClient.post(_ as String, _ as Map, _ as String) >> """{"submissionId": "fake-id", "key": "value"}""" - TestApplicationContext.register(HttpClient, mockClient) + def senderHelper = Mock(ReportStreamSenderHelper) + senderHelper.sendOrderToReportStream(underlyingOrder, fhirResourceId) >> Optional.of("fake-id") + TestApplicationContext.register(ReportStreamSenderHelper, senderHelper) def mockFhir = Mock(HapiFhir) - mockFhir.encodeResourceToJson(_ as String) >> "Mock order" + mockFhir.encodeResourceToJson(_ as String) >> underlyingOrder TestApplicationContext.register(HapiFhir, mockFhir) - def mockFormatter = Mock(Formatter) - mockFormatter.convertJsonToObject(_ as String, _ as TypeReference) >> Map.of("submissionId", "fake-id") - TestApplicationContext.register(Formatter, mockFormatter) - - def mockCache = Mock(Cache) - TestApplicationContext.register(Cache, mockCache) - TestApplicationContext.injectRegisteredImplementations() when: - ReportStreamOrderSender.getInstance().send(new OrderMock(null, null, "Mock order")) + ReportStreamOrderSender.getInstance().send(mockOrder) then: noExceptionThrown() } - - def "log the step to metadata when send order is called"() { - given: - - def mockAuthEngine = Mock(AuthEngine) - TestApplicationContext.register(AuthEngine, mockAuthEngine) - - def mockSecrets = Mock(Secrets) - TestApplicationContext.register(Secrets, mockSecrets) - - def mockClient = Mock(HttpClient) - mockClient.post(_ as String, _ as Map, _ as String) >> """{"submissionId": "fake-id", "key": "value"}""" - TestApplicationContext.register(HttpClient, mockClient) - - def mockFhir = Mock(HapiFhir) - mockFhir.encodeResourceToJson(_ as String) >> "Mock order" - TestApplicationContext.register(HapiFhir, mockFhir) - - def mockFormatter = Mock(Formatter) - mockFormatter.convertJsonToObject(_ as String, _ as TypeReference) >> Map.of("submissionId", "fake-id") - TestApplicationContext.register(Formatter, mockFormatter) - - def mockCache = Mock(Cache) - TestApplicationContext.register(Cache, mockCache) - - TestApplicationContext.injectRegisteredImplementations() - - when: - ReportStreamOrderSender.getInstance().send(new OrderMock(null, null, "Mock order")) - - then: - 1 * ReportStreamOrderSender.getInstance().metadata.put(_, EtorMetadataStep.SENT_TO_REPORT_STREAM) - } - - def "getSubmissionId logs submissionId if convertJsonToObject is successful"() { - given: - def mockSubmissionId = "fake-id" - def mockResponseBody = """{"submissionId": "${mockSubmissionId}", "key": "value"}""" - - TestApplicationContext.register(Formatter, Jackson.getInstance()) - - def mockLogger = Mock(Logger) - TestApplicationContext.register(Logger, mockLogger) - - TestApplicationContext.injectRegisteredImplementations() - - when: - def submissionId = ReportStreamOrderSender.getInstance().getSubmissionId(mockResponseBody) - - then: - submissionId.get() == mockSubmissionId - } - - def "getSubmissionId logs error if convertJsonToObject fails"() { - given: - def mockResponseBody = '{"submissionId": "fake-id", "key": "value"}' - def exception = new FormatterProcessingException("couldn't convert json", new Exception()) - - def mockFormatter = Mock(Formatter) - mockFormatter.convertJsonToObject(_ as String, _ as TypeReference) >> { throw exception } - TestApplicationContext.register(Formatter, mockFormatter) - - def mockLogger = Mock(Logger) - TestApplicationContext.register(Logger, mockLogger) - - TestApplicationContext.injectRegisteredImplementations() - - when: - ReportStreamOrderSender.getInstance().getSubmissionId(mockResponseBody) - - then: - 1 * mockLogger.logError(_ as String, exception) - } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSenderTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSenderTest.groovy index 250e87dc2..c6428150d 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSenderTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamResultSenderTest.groovy @@ -3,6 +3,7 @@ package gov.hhs.cdc.trustedintermediary.external.reportstream import gov.hhs.cdc.trustedintermediary.ResultMock import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext import gov.hhs.cdc.trustedintermediary.etor.results.ResultSender +import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir import spock.lang.Specification class ReportStreamResultSenderTest extends Specification { @@ -14,8 +15,23 @@ class ReportStreamResultSenderTest extends Specification { } def "send results works"() { + given: + def fhirResourceId = null + def underlyingResult = "Mock result" + def mockResult = new ResultMock(fhirResourceId, underlyingResult) + + def senderHelper = Mock(ReportStreamSenderHelper) + senderHelper.sendResultToReportStream(underlyingResult, fhirResourceId) >> Optional.of("fake-id") + TestApplicationContext.register(ReportStreamSenderHelper, senderHelper) + + def mockFhir = Mock(HapiFhir) + mockFhir.encodeResourceToJson(_ as String) >> underlyingResult + TestApplicationContext.register(HapiFhir, mockFhir) + + TestApplicationContext.injectRegisteredImplementations() + when: - ReportStreamResultSender.getInstance().send(new ResultMock(null, "Mock result")) + ReportStreamResultSender.getInstance().send(mockResult) then: noExceptionThrown() diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelperTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelperTest.groovy new file mode 100644 index 000000000..025553826 --- /dev/null +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/reportstream/ReportStreamSenderHelperTest.groovy @@ -0,0 +1,137 @@ +package gov.hhs.cdc.trustedintermediary.external.reportstream + +import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext +import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient +import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException +import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep +import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson +import gov.hhs.cdc.trustedintermediary.external.localfile.MockRSEndpointClient +import gov.hhs.cdc.trustedintermediary.wrappers.Logger +import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference +import spock.lang.Specification + +class ReportStreamSenderHelperTest extends Specification { + + def setup() { + TestApplicationContext.reset() + TestApplicationContext.init() + TestApplicationContext.register(ReportStreamSenderHelper, ReportStreamSenderHelper.getInstance()) + TestApplicationContext.register(MetricMetadata, Mock(MetricMetadata)) + } + + def "sendToReportStream works"() { + given: + def requestBody = "testBody" + def bearerToken = "fake-token" + def responseBody = """{"submissionId": "fake-id"}""" + + def mockFormatter = Mock(Formatter) + TestApplicationContext.register(Formatter, mockFormatter) + + def mockRsClient = Mock(RSEndpointClient) + TestApplicationContext.register(RSEndpointClient, mockRsClient) + + TestApplicationContext.injectRegisteredImplementations() + + when: + ReportStreamSenderHelper.getInstance().sendToReportStream(requestBody, _ as String, _ as String) + + then: + 1 * mockRsClient.getRsToken() >> "fake-token" + 1 * mockRsClient.requestWatersEndpoint(requestBody, bearerToken) >> responseBody + 1 * mockFormatter.convertJsonToObject(responseBody, _ as TypeReference) >> [submissionId: "fake-id"] + 1 * ReportStreamSenderHelper.getInstance().metadata.put(_, EtorMetadataStep.SENT_TO_REPORT_STREAM) + } + + def "sendOrderToReportStream works"() { + setup: + def body = "testBody" + def fhirResourceId = "testId" + def expected = Optional.of("result") + + def senderHelper = Spy(ReportStreamSenderHelper.getInstance()) + TestApplicationContext.injectRegisteredImplementations() + + when: + def order = senderHelper.sendOrderToReportStream(body, fhirResourceId) + + then: + order.get() == expected.get() + 1 * senderHelper.sendToReportStream(body, fhirResourceId, "order") >> expected + } + + def "sendResultToReportStream works"() { + setup: + def body = "testBody" + def fhirResourceId = "testId" + def expected = Optional.of("result") + + def senderHelper = Spy(ReportStreamSenderHelper.getInstance()) + TestApplicationContext.injectRegisteredImplementations() + + when: + def result = senderHelper.sendResultToReportStream(body, fhirResourceId) + + then: + result.get() == expected.get() + 1 * senderHelper.sendToReportStream(body, fhirResourceId, "result") >> expected + } + + def "sendToReportStream throws exception if RS client fails"() { + setup: + def mockEndpointClient = Mock(RSEndpointClient) + mockEndpointClient.getRsToken() >> { throw new ReportStreamEndpointClientException("couldn't get token", new Exception())} + TestApplicationContext.register(RSEndpointClient, mockEndpointClient) + + TestApplicationContext.injectRegisteredImplementations() + + when: + ReportStreamSenderHelper.getInstance().sendToReportStream("testBody", "testId", "testType") + + then: + thrown(UnableToSendMessageException) + } + + def "getSubmissionId logs submissionId if convertJsonToObject is successful"() { + given: + def mockSubmissionId = "fake-id" + def mockResponseBody = """{"submissionId": "${mockSubmissionId}", "key": "value"}""" + + TestApplicationContext.register(Formatter, Jackson.getInstance()) + + def mockLogger = Mock(Logger) + TestApplicationContext.register(Logger, mockLogger) + + TestApplicationContext.injectRegisteredImplementations() + + when: + def submissionId = ReportStreamSenderHelper.getInstance().getSubmissionId(mockResponseBody) + + then: + submissionId.get() == mockSubmissionId + } + + def "getSubmissionId logs error if convertJsonToObject fails"() { + given: + def mockResponseBody = '{"submissionId": "fake-id", "key": "value"}' + def exception = new FormatterProcessingException("couldn't convert json", new Exception()) + + def mockFormatter = Mock(Formatter) + mockFormatter.convertJsonToObject(_ as String, _ as TypeReference) >> { throw exception } + TestApplicationContext.register(Formatter, mockFormatter) + + def mockLogger = Mock(Logger) + TestApplicationContext.register(Logger, mockLogger) + + TestApplicationContext.injectRegisteredImplementations() + + when: + ReportStreamSenderHelper.getInstance().getSubmissionId(mockResponseBody) + + then: + 1 * mockLogger.logError(_ as String, exception) + } +}