From 77df6f38ecc09383e3910f19d9fffbee1f7bd83a Mon Sep 17 00:00:00 2001 From: Jakub Lidke Date: Mon, 12 May 2025 11:25:45 +0200 Subject: [PATCH] refactor: renamed misleading enum value TtpConsentStatus.IGNORED to TtpConsentStatus.UNKNOWN_CHECK_FILE also impl. ConsentCheckedIgnored has been renamed to ConsentCheckFileBased - since consent status should never be ignored. Also renamed ICheckConsent.isConsented ICheckConsent.getTtpConsentStatus since new method name is more descriptive. --- README.md | 2 +- .../input/MtbFileRestControllerTest.kt | 6 ++--- .../consent/ConsentCheckFileBased.java | 9 +++++++ .../consent/ConsentCheckedIgnored.java | 9 ------- .../processor/consent/GicsConsentService.java | 10 +++---- .../etl/processor/consent/ICheckConsent.java | 2 +- .../processor/consent/TtpConsentStatus.java | 6 +++-- .../etl/processor/config/AppConfiguration.kt | 4 +-- .../etl/processor/input/KafkaInputListener.kt | 4 +-- .../processor/input/MtbFileRestController.kt | 10 +++---- .../processor/services/RequestProcessor.kt | 2 +- .../consent/GicsConsentServiceTest.java | 8 +++--- .../processor/input/KafkaInputListenerTest.kt | 6 ++--- .../input/MtbFileRestControllerTest.kt | 26 ++++++++++++------- .../services/RequestProcessorTest.kt | 8 +++--- 15 files changed, 59 insertions(+), 53 deletions(-) create mode 100644 src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckFileBased.java delete mode 100644 src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckedIgnored.java diff --git a/README.md b/README.md index a903678..ee59a32 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Wurde die Verwendung von gPAS konfiguriert, so sind weitere Angaben zu konfiguri Ab gIcs Version 2.13.0 kann per [REST-Schnittstelle](https://simplifier.net/guide/ttp-fhir-gateway-ig/ImplementationGuide-markdown-Einwilligungsmanagement-Operations-isConsented?version=current) der Einwilligungsstatus abgefragt werden. Vor der MTB-Übertragung kann der zum Sendezeitpunkt verfügbarer Einwilligungsstatus über Endpunkt *isConsented* abgefragt werden. -Falls diese Prüfung aktiviert wurde, wird der Einwilligungsstatus dem in der MTB Datei vorgezogen und überschreibt diesen. +Falls diese Prüfung aktiviert wurde, wird der Einwilligungsstatus dem in der MTB Datei vorgezogen und der Wert in der MTB-Datei wird dabei ignoriert. Falls in diesem Fall die Statusprüfung fehlschlägt, wird Status **abgelehnt** angenommen. Ist die Prüfung über gIcs deaktiviert, wird der eingetragene Einwilligungsstatus der übermittelten MTB Datei geprüft. diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt index d6a0dc2..c463fd0 100644 --- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt +++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt @@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import de.ukw.ccc.bwhc.dto.* import dev.dnpm.etl.processor.anyValueClass import dev.dnpm.etl.processor.config.AppSecurityConfiguration -import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored +import dev.dnpm.etl.processor.consent.ConsentCheckFileBased import dev.dnpm.etl.processor.consent.TtpConsentStatus import dev.dnpm.etl.processor.consent.ICheckConsent import dev.dnpm.etl.processor.security.TokenRepository @@ -55,7 +55,7 @@ import org.springframework.test.web.servlet.post classes = [ MtbFileRestController::class, AppSecurityConfiguration::class, - ConsentCheckedIgnored::class, ICheckConsent::class + ConsentCheckFileBased::class, ICheckConsent::class ] ) @MockitoBean(types = [TokenRepository::class, RequestProcessor::class]) @@ -143,7 +143,7 @@ class MtbFileRestControllerTest { status { isAccepted() } } - verify(requestProcessor, times(1)).processDeletion(anyValueClass(), eq(TtpConsentStatus.IGNORED)) + verify(requestProcessor, times(1)).processDeletion(anyValueClass(), eq(TtpConsentStatus.UNKNOWN_CHECK_FILE)) } @Test diff --git a/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckFileBased.java b/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckFileBased.java new file mode 100644 index 0000000..5876c13 --- /dev/null +++ b/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckFileBased.java @@ -0,0 +1,9 @@ +package dev.dnpm.etl.processor.consent; + +public class ConsentCheckFileBased implements ICheckConsent{ + + @Override + public TtpConsentStatus getTtpConsentStatus(String personIdentifierValue) { + return TtpConsentStatus.UNKNOWN_CHECK_FILE; + } +} diff --git a/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckedIgnored.java b/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckedIgnored.java deleted file mode 100644 index d76eece..0000000 --- a/src/main/java/dev/dnpm/etl/processor/consent/ConsentCheckedIgnored.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.dnpm.etl.processor.consent; - -public class ConsentCheckedIgnored implements ICheckConsent{ - - @Override - public TtpConsentStatus isConsented(String personIdentifierValue) { - return TtpConsentStatus.IGNORED; - } -} diff --git a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java index 53dfee6..876e1da 100644 --- a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java +++ b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java @@ -58,7 +58,7 @@ public class GicsConsentService implements ICheckConsent { throw new IllegalArgumentException( "gICS base URL is empty - should call gICS with false configuration."); } - url = UriComponentsBuilder.fromHttpUrl(gIcsBaseUri).path(IS_CONSENTED_ENDPOINT) + url = UriComponentsBuilder.fromUriString(gIcsBaseUri).path(IS_CONSENTED_ENDPOINT) .toUriString(); } return url; @@ -147,7 +147,7 @@ public class GicsConsentService implements ICheckConsent { } @Override - public TtpConsentStatus isConsented(String personIdentifierValue) { + public TtpConsentStatus getTtpConsentStatus(String personIdentifierValue) { var parameter = GicsConsentService.getIsConsentedParam(gIcsConfigProperties, personIdentifierValue); @@ -176,10 +176,8 @@ public class GicsConsentService implements ICheckConsent { return TtpConsentStatus.CONSENT_MISSING_OR_REJECTED; } } else if (response instanceof OperationOutcome outcome) { - - log.error( - "failed to get consent status from ttp. probably configuration error. outcome: ", - fhirContext.newJsonParser().encodeToString(outcome)); + log.error("failed to get consent status from ttp. probably configuration error. " + + "outcome: '{}'", fhirContext.newJsonParser().encodeToString(outcome)); } } catch (DataFormatException dfe) { diff --git a/src/main/java/dev/dnpm/etl/processor/consent/ICheckConsent.java b/src/main/java/dev/dnpm/etl/processor/consent/ICheckConsent.java index da50e62..01c4483 100644 --- a/src/main/java/dev/dnpm/etl/processor/consent/ICheckConsent.java +++ b/src/main/java/dev/dnpm/etl/processor/consent/ICheckConsent.java @@ -3,6 +3,6 @@ package dev.dnpm.etl.processor.consent; public interface ICheckConsent { - TtpConsentStatus isConsented(String personIdentifierValue); + TtpConsentStatus getTtpConsentStatus(String personIdentifierValue); } diff --git a/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java b/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java index 375cdd1..f98f4f5 100644 --- a/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java +++ b/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java @@ -7,12 +7,14 @@ public enum TtpConsentStatus { CONSENTED, CONSENT_MISSING_OR_REJECTED, + /** * Due technical problems consent status is unknown */ FAILED_TO_ASK, + /** - * We assume received files are consented + * Consent status is validate via file property 'consent.status' */ - IGNORED + UNKNOWN_CHECK_FILE } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt index b276bfd..2423a6c 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt @@ -20,7 +20,7 @@ package dev.dnpm.etl.processor.config import com.fasterxml.jackson.databind.ObjectMapper -import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored +import dev.dnpm.etl.processor.consent.ConsentCheckFileBased import dev.dnpm.etl.processor.consent.ICheckConsent import dev.dnpm.etl.processor.consent.GicsConsentService import dev.dnpm.etl.processor.monitoring.ConnectionCheckResult @@ -183,7 +183,7 @@ class AppConfiguration { @Bean @ConditionalOnMissingBean fun constService(): ICheckConsent { - return ConsentCheckedIgnored() + return ConsentCheckFileBased() } @Bean diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt index 544230a..415a68f 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt @@ -77,12 +77,12 @@ class KafkaInputListener( } else { logger.debug("Accepted MTB File and process deletion") if (requestId.isBlank()) { - requestProcessor.processDeletion(patientId, TtpConsentStatus.IGNORED) + requestProcessor.processDeletion(patientId, TtpConsentStatus.UNKNOWN_CHECK_FILE) } else { requestProcessor.processDeletion( patientId, requestId, - TtpConsentStatus.IGNORED + TtpConsentStatus.UNKNOWN_CHECK_FILE ) } } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt index 8a418fc..d9d9b7d 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt @@ -48,7 +48,7 @@ class MtbFileRestController( @PostMapping(consumes = [MediaType.APPLICATION_JSON_VALUE]) fun mtbFile(@RequestBody mtbFile: MtbFile): ResponseEntity { val consentStatusBooleanPair = checkConsentStatus(mtbFile) - var ttpConsentStatus = consentStatusBooleanPair.first + val ttpConsentStatus = consentStatusBooleanPair.first val isConsentOK = consentStatusBooleanPair.second if (isConsentOK) { logger.debug("Accepted MTB File (bwHC V1) for processing") @@ -63,14 +63,14 @@ class MtbFileRestController( } private fun checkConsentStatus(mtbFile: MtbFile): Pair { - var ttpConsentStatus = constService.isConsented(mtbFile.patient.id) + var ttpConsentStatus = constService.getTtpConsentStatus(mtbFile.patient.id) val isConsentOK = - (ttpConsentStatus.equals(TtpConsentStatus.IGNORED) && mtbFile.consent.status == Consent.Status.ACTIVE) || + (ttpConsentStatus.equals(TtpConsentStatus.UNKNOWN_CHECK_FILE) && mtbFile.consent.status == Consent.Status.ACTIVE) || ttpConsentStatus.equals( TtpConsentStatus.CONSENTED ) - if (ttpConsentStatus.equals(TtpConsentStatus.IGNORED) && mtbFile.consent.status == Consent.Status.REJECTED) { + if (ttpConsentStatus.equals(TtpConsentStatus.UNKNOWN_CHECK_FILE) && mtbFile.consent.status == Consent.Status.REJECTED) { // in case ttp check is disabled - we propagate rejected status anyway ttpConsentStatus = TtpConsentStatus.CONSENT_MISSING_OR_REJECTED } @@ -87,7 +87,7 @@ class MtbFileRestController( @DeleteMapping(path = ["{patientId}"]) fun deleteData(@PathVariable patientId: String): ResponseEntity { logger.debug("Accepted patient ID to process deletion") - requestProcessor.processDeletion(PatientId(patientId), TtpConsentStatus.IGNORED) + requestProcessor.processDeletion(PatientId(patientId), TtpConsentStatus.UNKNOWN_CHECK_FILE) return ResponseEntity.accepted().build() } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt index e17e38e..edc4288 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt @@ -140,7 +140,7 @@ class RequestProcessor( val requestStatus: RequestStatus = when (isConsented) { TtpConsentStatus.CONSENT_MISSING_OR_REJECTED -> RequestStatus.NO_CONSENT TtpConsentStatus.FAILED_TO_ASK -> RequestStatus.ERROR - TtpConsentStatus.CONSENTED, TtpConsentStatus.IGNORED -> RequestStatus.UNKNOWN + TtpConsentStatus.CONSENTED, TtpConsentStatus.UNKNOWN_CHECK_FILE -> RequestStatus.UNKNOWN } requestService.save( diff --git a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java index 5a633f6..f3e3e91 100644 --- a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java +++ b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java @@ -48,7 +48,7 @@ public class GicsConsentServiceTest { } @Test - void isConsented() { + void getTtpConsentStatus() { final Parameters responseConsented = new Parameters().addParameter( new ParametersParameterComponent().setName("consented") .setValue(new BooleanType().setValue(true))); @@ -59,7 +59,7 @@ public class GicsConsentServiceTest { .encodeResourceToString(responseConsented), MediaType.APPLICATION_JSON)); - var consentStatus = gicsConsentService.isConsented("123456"); + var consentStatus = gicsConsentService.getTtpConsentStatus("123456"); assertThat(consentStatus).isEqualTo(TtpConsentStatus.CONSENTED); } @@ -76,7 +76,7 @@ public class GicsConsentServiceTest { .encodeResourceToString(responseRevoced), MediaType.APPLICATION_JSON)); - var consentStatus = gicsConsentService.isConsented("123456"); + var consentStatus = gicsConsentService.getTtpConsentStatus("123456"); assertThat(consentStatus).isEqualTo(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED); } @@ -94,7 +94,7 @@ public class GicsConsentServiceTest { .encodeResourceToString(responseErrorOutcome), MediaType.APPLICATION_JSON)); - var consentStatus = gicsConsentService.isConsented("123456"); + var consentStatus = gicsConsentService.getTtpConsentStatus("123456"); assertThat(consentStatus).isEqualTo(TtpConsentStatus.FAILED_TO_ASK); } diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt index 9b8b634..fbcfb3f 100644 --- a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt +++ b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt @@ -94,7 +94,7 @@ class KafkaInputListenerTest { verify(requestProcessor, times(1)).processDeletion( anyValueClass(), - eq(TtpConsentStatus.IGNORED) + eq(TtpConsentStatus.UNKNOWN_CHECK_FILE) ) } @@ -149,7 +149,7 @@ class KafkaInputListenerTest { ) ) verify(requestProcessor, times(1)).processDeletion(anyValueClass(), anyValueClass(), eq( - TtpConsentStatus.IGNORED)) + TtpConsentStatus.UNKNOWN_CHECK_FILE)) } @Test @@ -181,7 +181,7 @@ class KafkaInputListenerTest { ) ) verify(requestProcessor, times(0)).processDeletion(anyValueClass(), anyValueClass(), eq( - TtpConsentStatus.IGNORED)) + TtpConsentStatus.UNKNOWN_CHECK_FILE)) } } diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt index 655b426..e375148 100644 --- a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt +++ b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt @@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import de.ukw.ccc.bwhc.dto.* import de.ukw.ccc.bwhc.dto.Consent.Status import dev.dnpm.etl.processor.CustomMediaType -import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored +import dev.dnpm.etl.processor.consent.ConsentCheckFileBased import dev.dnpm.etl.processor.consent.GicsConsentService import dev.dnpm.etl.processor.consent.TtpConsentStatus import dev.dnpm.etl.processor.services.RequestProcessor @@ -67,7 +67,9 @@ class MtbFileRestControllerTest { @Mock requestProcessor: RequestProcessor ) { this.requestProcessor = requestProcessor - val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored()) + val controller = MtbFileRestController(requestProcessor, + ConsentCheckFileBased() + ) this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build() } @@ -113,7 +115,7 @@ class MtbFileRestControllerTest { verify(requestProcessor, times(1)).processDeletion( anyValueClass(), - org.mockito.kotlin.eq(TtpConsentStatus.IGNORED) + org.mockito.kotlin.eq(TtpConsentStatus.UNKNOWN_CHECK_FILE) ) } } @@ -147,7 +149,7 @@ class MtbFileRestControllerTest { @ValueSource(strings = ["ACTIVE", "REJECTED"]) fun shouldProcessPostRequest(status: String) { - whenever(gicsConsentService.isConsented(any())).thenReturn(TtpConsentStatus.CONSENTED) + whenever(gicsConsentService.getTtpConsentStatus(any())).thenReturn(TtpConsentStatus.CONSENTED) mockMvc.post("/mtbfile") { content = @@ -167,7 +169,7 @@ class MtbFileRestControllerTest { @ValueSource(strings = ["ACTIVE", "REJECTED"]) fun shouldProcessPostRequestWithRejectedConsent(status: String) { - whenever(gicsConsentService.isConsented(any())).thenReturn(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED) + whenever(gicsConsentService.getTtpConsentStatus(any())).thenReturn(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED) mockMvc.post("/mtbfile") { content = @@ -197,9 +199,9 @@ class MtbFileRestControllerTest { verify(requestProcessor, times(1)).processDeletion( anyValueClass(), - org.mockito.kotlin.eq(TtpConsentStatus.IGNORED) + org.mockito.kotlin.eq(TtpConsentStatus.UNKNOWN_CHECK_FILE) ) - verify(gicsConsentService, times(0)).isConsented(any()) + verify(gicsConsentService, times(0)).getTtpConsentStatus(any()) } } @@ -217,7 +219,9 @@ class MtbFileRestControllerTest { @Mock requestProcessor: RequestProcessor ) { this.requestProcessor = requestProcessor - val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored()) + val controller = MtbFileRestController(requestProcessor, + ConsentCheckFileBased() + ) this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build() } @@ -264,7 +268,7 @@ class MtbFileRestControllerTest { verify(requestProcessor, times(1)).processDeletion( anyValueClass(), org.mockito.kotlin.eq( - TtpConsentStatus.IGNORED + TtpConsentStatus.UNKNOWN_CHECK_FILE ) ) } @@ -282,7 +286,9 @@ class MtbFileRestControllerTest { @Mock requestProcessor: RequestProcessor ) { this.requestProcessor = requestProcessor - val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored()) + val controller = MtbFileRestController(requestProcessor, + ConsentCheckFileBased() + ) this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build() } diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt index 61b5dbb..f443243 100644 --- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt +++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt @@ -344,7 +344,7 @@ class RequestProcessorTest { MtbFileSender.Response(status = RequestStatus.UNKNOWN) }.whenever(sender).send(any()) - this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED) + this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE) val requestCaptor = argumentCaptor() verify(requestService, times(1)).save(requestCaptor.capture()) @@ -362,7 +362,7 @@ class RequestProcessorTest { MtbFileSender.Response(status = RequestStatus.SUCCESS) }.whenever(sender).send(any()) - this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED) + this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE) val eventCaptor = argumentCaptor() verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture()) @@ -380,7 +380,7 @@ class RequestProcessorTest { MtbFileSender.Response(status = RequestStatus.ERROR) }.whenever(sender).send(any()) - this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED) + this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE) val eventCaptor = argumentCaptor() verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture()) @@ -392,7 +392,7 @@ class RequestProcessorTest { fun testShouldSendDeleteRequestWithPseudonymErrorAndSaveErrorRequestStatus() { doThrow(RuntimeException()).whenever(pseudonymizeService).patientPseudonym(anyValueClass()) - this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED) + this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE) val requestCaptor = argumentCaptor() verify(requestService, times(1)).save(requestCaptor.capture())