summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt9
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt9
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt80
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt81
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt64
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt48
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt16
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt13
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt70
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt12
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt63
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt929
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt33
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt56
14 files changed, 1088 insertions, 395 deletions
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
index b940537..d543f87 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
@@ -21,8 +21,9 @@
package dev.dnpm.etl.processor.config
import com.fasterxml.jackson.databind.node.ObjectNode
-import dev.pcvolkmer.mv64e.mtb.Mtb
-import dev.pcvolkmer.mv64e.mtb.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.ResearchConsent
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -78,10 +79,10 @@ class Jackson3ConfigTest {
val inputConsentJson =
Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("fake_broadConsent_mii_response_permit.json"))?.readAllBytes()?.decodeToString()
- val mtb = this.jacksonConfig.jsonMapper().readValue<Mtb>(inputMtbFileJson, Mtb::class.java)
+ val mtb = this.jacksonConfig.jsonMapper().readValue<PatientRecord>(inputMtbFileJson, PatientRecord::class.java)
// Still use Jackson2 ObjectMapper since MTB DTO requires Jackson2 ObjectNode
val consentJsonNode = Jackson2Config().objectMapper().readTree(inputConsentJson)
- mtb.metadata = MvhMetadata.builder().researchConsents(listOf(MvhMetadata.ResearchConsent.from(consentJsonNode as ObjectNode))).build()
+ mtb.metadata = MvhMetadata.builder().researchConsents(listOf(ResearchConsent.from(consentJsonNode as ObjectNode))).build()
val actual = this.jacksonConfig.jsonMapper().writeValueAsString(mtb)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
index e734c6f..4411e70 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
@@ -21,8 +21,9 @@
package dev.dnpm.etl.processor.config
import com.fasterxml.jackson.databind.node.ObjectNode
-import dev.pcvolkmer.mv64e.mtb.Mtb
-import dev.pcvolkmer.mv64e.mtb.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.ResearchConsent
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -78,9 +79,9 @@ class JacksonConfigTest {
val inputConsentJson =
Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("fake_broadConsent_mii_response_permit.json"))?.readAllBytes()?.decodeToString()
- val mtb = this.jacksonConfig.objectMapper().readValue<Mtb>(inputMtbFileJson, Mtb::class.java)
+ val mtb = this.jacksonConfig.objectMapper().readValue<PatientRecord>(inputMtbFileJson, PatientRecord::class.java)
val consentJsonNode = this.jacksonConfig.objectMapper().readTree(inputConsentJson)
- mtb.metadata = MvhMetadata.builder().researchConsents(listOf(MvhMetadata.ResearchConsent.from(consentJsonNode as ObjectNode))).build()
+ mtb.metadata = MvhMetadata.builder().researchConsents(listOf(ResearchConsent.from(consentJsonNode as ObjectNode))).build()
val actual = this.jacksonConfig.objectMapper().writeValueAsString(mtb)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
deleted file mode 100644
index 30e3823..0000000
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * This file is part of ETL-Processor
- *
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package dev.dnpm.etl.processor.consent
-
-import ca.uhn.fhir.context.FhirContext
-import dev.dnpm.etl.processor.config.AppConfigProperties
-import dev.dnpm.etl.processor.config.GIcsConfigProperties
-import dev.dnpm.etl.processor.services.ConsentProcessor
-import org.assertj.core.api.Assertions.assertThat
-import org.hl7.fhir.r4.model.Bundle
-import org.hl7.fhir.r4.model.Consent
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.extension.ExtendWith
-import org.junit.jupiter.params.ParameterizedTest
-import org.junit.jupiter.params.provider.CsvSource
-import org.mockito.Mock
-import org.mockito.junit.jupiter.MockitoExtension
-import tools.jackson.databind.json.JsonMapper
-import java.util.*
-
-@ExtendWith(MockitoExtension::class)
-class ConsentProcessorTest {
-
- lateinit var consentProcessor: ConsentProcessor
-
- val jsonMapper = JsonMapper()
- val fhirContext = FhirContext.forR4()
-
- @BeforeEach
- fun setup(@Mock consentService: IConsentService) {
- val appConfigProperties = AppConfigProperties()
- val gIcsConfigProperties = GIcsConfigProperties("http://localhost")
-
- this.consentProcessor =
- ConsentProcessor(
- appConfigProperties,
- gIcsConfigProperties,
- jsonMapper,
- fhirContext,
- consentService,
- )
- }
-
- @ParameterizedTest
- @CsvSource(value = ["permittedConsentBundle.json,permit", "deniedConsentBundle.json,deny"])
- fun checkGetProvisionTypeByPolicyCode(filename: String, expected: String) {
- val bundle =
- fhirContext
- .newJsonParser()
- .parseResource(this.javaClass.classLoader.getResourceAsStream(filename))
- assertThat(bundle).isInstanceOf(Bundle::class.java)
-
- val actual =
- consentProcessor.getProvisionTypeByPolicyCode(
- bundle as Bundle,
- Date(),
- ConsentDomain.BROAD_CONSENT,
- )
-
- assertThat(actual).isEqualTo(Consent.ConsentProvisionType.valueOf(expected.uppercase()))
- }
-}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
index 284c552..3cf54fe 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
@@ -21,7 +21,16 @@
package dev.dnpm.etl.processor.consent
import dev.dnpm.etl.processor.ArgProvider
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.ConsentProvisionType
+import dev.pcvolkmer.mv64e.model.GenderCoding
+import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.Reference
import java.time.Instant
import java.util.*
import org.assertj.core.api.Assertions.assertThat
@@ -54,7 +63,7 @@ class Dnpm21BasedConsentEvaluatorTest {
@ParameterizedTest
@ArgumentsSource(WithGicsMtbFileProvider::class)
fun test(
- mtbFile: Mtb,
+ mtbFile: PatientRecord,
ttpConsentStatus: TtpConsentStatus,
expectedConsentEvaluation: ConsentEvaluation,
) {
@@ -77,7 +86,7 @@ class Dnpm21BasedConsentEvaluatorTest {
@ParameterizedTest
@ArgumentsSource(MtbFileProvider::class)
- fun test(mtbFile: Mtb, expectedConsentEvaluation: ConsentEvaluation) {
+ fun test(mtbFile: PatientRecord, expectedConsentEvaluation: ConsentEvaluation) {
assertThat(consentEvaluator.check(mtbFile)).isEqualTo(expectedConsentEvaluation)
}
}
@@ -88,120 +97,120 @@ class Dnpm21BasedConsentEvaluatorTest {
ArgProvider(
// Has file ModelProjectConsent and broad consent => consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.BROAD_CONSENT_GIVEN,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_GIVEN, true),
),
// Has file ModelProjectConsent and broad consent missing => no consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.BROAD_CONSENT_MISSING,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_MISSING, false),
),
// Has file ModelProjectConsent and broad consent missing or rejected => no consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.BROAD_CONSENT_MISSING_OR_REJECTED,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_MISSING_OR_REJECTED, false),
),
// Has file ModelProjectConsent and MV consent => consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.GENOM_DE_CONSENT_SEQUENCING_PERMIT,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_CONSENT_SEQUENCING_PERMIT, true),
),
// Has file ModelProjectConsent and MV consent rejected => no consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.GENOM_DE_SEQUENCING_REJECTED,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_SEQUENCING_REJECTED, false),
),
// Has file ModelProjectConsent and MV consent missing => no consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.GENOM_DE_CONSENT_MISSING,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_CONSENT_MISSING, false),
),
// Has file ModelProjectConsent and no broad consent result => consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.UNKNOWN_CHECK_FILE,
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, true),
),
// Has file ModelProjectConsent and failed to ask => no consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
TtpConsentStatus.FAILED_TO_ASK,
ConsentEvaluation(TtpConsentStatus.FAILED_TO_ASK, false),
),
// File ModelProjectConsent rejected and broad consent => consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.BROAD_CONSENT_GIVEN,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_GIVEN, true),
),
// File ModelProjectConsent rejected and broad consent missing => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.BROAD_CONSENT_MISSING,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_MISSING, false),
),
// File ModelProjectConsent rejected and broad consent missing or rejected => no consent
// given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.BROAD_CONSENT_MISSING_OR_REJECTED,
ConsentEvaluation(TtpConsentStatus.BROAD_CONSENT_MISSING_OR_REJECTED, false),
),
// File ModelProjectConsent rejected and MV consent => consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.GENOM_DE_CONSENT_SEQUENCING_PERMIT,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_CONSENT_SEQUENCING_PERMIT, true),
),
// File ModelProjectConsent rejected and MV consent rejected => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.GENOM_DE_SEQUENCING_REJECTED,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_SEQUENCING_REJECTED, false),
),
// File ModelProjectConsent rejected and MV consent missing => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.GENOM_DE_CONSENT_MISSING,
ConsentEvaluation(TtpConsentStatus.GENOM_DE_CONSENT_MISSING, false),
),
// File ModelProjectConsent rejected and no broad consent result => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.UNKNOWN_CHECK_FILE,
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
// File ModelProjectConsent rejected and failed to ask => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
TtpConsentStatus.FAILED_TO_ASK,
ConsentEvaluation(TtpConsentStatus.FAILED_TO_ASK, false),
),
) {
companion object {
- fun buildMtb(consentProvision: ConsentProvision): Mtb {
- return Mtb.builder()
+ fun buildMtb(consentProvision: ConsentProvisionType): PatientRecord {
+ return PatientRecord.builder()
.patient(
Patient.builder()
.id("TEST_12345678")
.birthDate(Date.from(Instant.parse("2000-08-08T12:34:56Z")))
- .gender(GenderCoding.builder().code(GenderCodingCode.MALE).build())
+ .gender(GenderCoding.builder().code(GenderCoding.CodeEnum.MALE).build())
.build()
)
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
.date(Date())
.type(consentProvision)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
@@ -229,55 +238,55 @@ class Dnpm21BasedConsentEvaluatorTest {
ArgProvider(
// Has file consent => consent given
Arguments.of(
- buildMtb(ConsentProvision.PERMIT),
+ buildMtb(ConsentProvisionType.PERMIT),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, true),
),
// File consent rejected => no consent given
Arguments.of(
- buildMtb(ConsentProvision.DENY),
+ buildMtb(ConsentProvisionType.DENY),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
// policy REIDENTIFICATION has no effect on ConsentEvaluation
Arguments.of(
- buildMtb(ModelProjectConsentPurpose.REIDENTIFICATION, ConsentProvision.DENY),
+ buildMtb(ModelProjectConsentPurpose.REIDENTIFICATION, ConsentProvisionType.DENY),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
Arguments.of(
- buildMtb(ModelProjectConsentPurpose.REIDENTIFICATION, ConsentProvision.PERMIT),
+ buildMtb(ModelProjectConsentPurpose.REIDENTIFICATION, ConsentProvisionType.PERMIT),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
// policy CASE_IDENTIFICATION has no effect on ConsentEvaluation
Arguments.of(
- buildMtb(ModelProjectConsentPurpose.CASE_IDENTIFICATION, ConsentProvision.DENY),
+ buildMtb(ModelProjectConsentPurpose.CASE_IDENTIFICATION, ConsentProvisionType.DENY),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
Arguments.of(
- buildMtb(ModelProjectConsentPurpose.CASE_IDENTIFICATION, ConsentProvision.PERMIT),
+ buildMtb(ModelProjectConsentPurpose.CASE_IDENTIFICATION, ConsentProvisionType.PERMIT),
ConsentEvaluation(TtpConsentStatus.UNKNOWN_CHECK_FILE, false),
),
) {
companion object {
- fun buildMtb(consentProvision: ConsentProvision): Mtb {
+ fun buildMtb(consentProvision: ConsentProvisionType): PatientRecord {
return buildMtb(ModelProjectConsentPurpose.SEQUENCING, consentProvision)
}
- fun buildMtb(policy: ModelProjectConsentPurpose, consentProvision: ConsentProvision): Mtb {
- return Mtb.builder()
+ fun buildMtb(policy: ModelProjectConsentPurpose, consentProvision: ConsentProvisionType): PatientRecord {
+ return PatientRecord.builder()
.patient(
Patient.builder()
.id("TEST_12345678")
.birthDate(Date.from(Instant.parse("2000-08-08T12:34:56Z")))
- .gender(GenderCoding.builder().code(GenderCodingCode.MALE).build())
+ .gender(GenderCoding.builder().code(GenderCoding.CodeEnum.MALE).build())
.build()
)
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
.date(Date())
.type(consentProvision)
.purpose(policy)
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 eeb6288..9a5a2ee 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
@@ -25,7 +25,13 @@ import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.consent.ConsentEvaluator
import dev.dnpm.etl.processor.consent.TtpConsentStatus
import dev.dnpm.etl.processor.services.RequestProcessor
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.ConsentProvisionType
+import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.header.internals.RecordHeader
import org.apache.kafka.common.header.internals.RecordHeaders
@@ -69,16 +75,16 @@ class KafkaInputListenerTest {
@Test
fun shouldProcessMtbFileRequest() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.PERMIT)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -93,18 +99,18 @@ class KafkaInputListenerTest {
ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>())
}
@Test
fun shouldProcessRequestEvenIfNoConsentInformation() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf()
)
@@ -117,22 +123,22 @@ class KafkaInputListenerTest {
kafkaInputListener.onMessage(
ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>())
}
@Test
fun shouldProcessMtbFileRequestWithExistingRequestId() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.PERMIT)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -161,22 +167,22 @@ class KafkaInputListenerTest {
)
)
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>(), anyValueClass())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>(), anyValueClass())
}
@Test
fun shouldProcessRequestWithoutConsentGiven() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.DENY)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.DENY)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -204,22 +210,22 @@ class KafkaInputListenerTest {
Optional.empty(),
)
)
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>(), anyValueClass())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>(), anyValueClass())
}
@Test
fun shouldProcessDnpmV2Request() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.DENY)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.DENY)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -255,22 +261,22 @@ class KafkaInputListenerTest {
Optional.empty(),
)
)
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>(), anyValueClass())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>(), anyValueClass())
}
@Test
fun shouldProcessDnpmV2DeleteRequest() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("DUMMY_12345678").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.DENY)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.DENY)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -323,7 +329,7 @@ class KafkaInputListenerTest {
ConsumerRecord("testtopic", 0, 0, "", content)
)
- val result = verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
+ val result = verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>())
assertThat(result).isFalse()
}
}
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 9ee4b2b..75d69dc 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
@@ -27,7 +27,17 @@ import dev.dnpm.etl.processor.consent.ConsentEvaluator
import dev.dnpm.etl.processor.consent.TtpConsentStatus
import dev.dnpm.etl.processor.input.Dnpm21MtbFile.Companion.buildMtb
import dev.dnpm.etl.processor.services.RequestProcessor
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.ConsentProvisionType
+import dev.pcvolkmer.mv64e.model.GenderCoding
+import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.Reference
+import org.flywaydb.core.internal.configuration.resolvers.ProvisionerMode
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
@@ -78,7 +88,7 @@ class MtbFileRestControllerTest {
.readAllBytes()
.toString(Charsets.UTF_8)
- whenever { requestProcessor.processMtbFile(any<Mtb>()) }.thenReturn(true)
+ whenever { requestProcessor.processMtbFile(any<PatientRecord>()) }.thenReturn(true)
mockMvc
.post("/mtb") {
@@ -87,13 +97,13 @@ class MtbFileRestControllerTest {
}
.andExpect { status { isAccepted() } }
- verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
+ verify(requestProcessor, times(1)).processMtbFile(any<PatientRecord>())
}
@ParameterizedTest
@ArgumentsSource(Dnpm21MtbFile::class)
- fun shouldProcessPostRequest(mtb: Mtb) {
- whenever { requestProcessor.processMtbFile(any<Mtb>()) }.thenReturn(true)
+ fun shouldProcessPostRequest(mtb: PatientRecord) {
+ whenever { requestProcessor.processMtbFile(any<PatientRecord>()) }.thenReturn(true)
mockMvc
.post("/mtbfile") {
@@ -132,12 +142,12 @@ class MtbFileRestControllerTest {
buildMtb(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
.date(Date())
- .type(ConsentProvision.PERMIT)
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -147,7 +157,7 @@ class MtbFileRestControllerTest {
.build()
)
- whenever { requestProcessor.processMtbFile(any<Mtb>()) }.thenReturn(true)
+ whenever { requestProcessor.processMtbFile(any<PatientRecord>()) }.thenReturn(true)
mockMvc
.post(url) {
@@ -200,7 +210,7 @@ class Dnpm21MtbFile :
Arguments.of(
buildMtb(
MvhMetadata.builder()
- .modelProjectConsent(ModelProjectConsent.builder().build())
+ .modelProjectConsent(MvhMetadataModelProjectConsent.builder().build())
.build()
)
),
@@ -209,12 +219,12 @@ class Dnpm21MtbFile :
buildMtb(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
.date(Date())
- .type(ConsentProvision.PERMIT)
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -229,12 +239,12 @@ class Dnpm21MtbFile :
buildMtb(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
.date(Date())
- .type(ConsentProvision.PERMIT)
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -247,13 +257,13 @@ class Dnpm21MtbFile :
) {
companion object {
- fun buildMtb(metadata: MvhMetadata?): Mtb {
- return Mtb.builder()
+ fun buildMtb(metadata: MvhMetadata?): PatientRecord {
+ return PatientRecord.builder()
.patient(
Patient.builder()
.id("TEST_12345678")
.birthDate(Date.from(Instant.parse("2000-08-08T12:34:56Z")))
- .gender(GenderCoding.builder().code(GenderCodingCode.MALE).build())
+ .gender(GenderCoding.builder().code(GenderCoding.CodeEnum.MALE).build())
.build()
)
.metadata(metadata)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
index ee840a8..9384aae 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
@@ -25,7 +25,11 @@ import dev.dnpm.etl.processor.PatientPseudonym
import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.config.KafkaProperties
import dev.dnpm.etl.processor.monitoring.RequestStatus
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.GenderCoding
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.PeriodDate
+import dev.pcvolkmer.mv64e.model.Reference
import org.apache.kafka.clients.producer.ProducerRecord
import org.apache.kafka.clients.producer.RecordMetadata
import org.apache.kafka.common.TopicPartition
@@ -252,13 +256,13 @@ class KafkaMtbFileSenderTest {
val TEST_REQUEST_ID = RequestId("TestId")
val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
- fun dnpmV2MtbFile(): Mtb {
- return Mtb().apply {
+ fun dnpmV2MtbFile(): PatientRecord {
+ return PatientRecord().apply {
this.patient =
- dev.pcvolkmer.mv64e.mtb.Patient().apply {
+ dev.pcvolkmer.mv64e.model.Patient().apply {
this.id = "PID"
this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ this.gender = GenderCoding().apply { this.code = GenderCoding.CodeEnum.MALE }
}
this.episodesOfCare =
listOf(
@@ -271,7 +275,7 @@ class KafkaMtbFileSenderTest {
}
}
- fun dnmpV2kafkaRecordData(requestId: RequestId): Mtb {
+ fun dnmpV2kafkaRecordData(requestId: RequestId): PatientRecord {
return DnpmV2MtbFileRequest(requestId, dnpmV2MtbFile()).content
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
index d95ced0..3a0b3f0 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
@@ -28,7 +28,12 @@ import dev.dnpm.etl.processor.config.AppConfiguration
import dev.dnpm.etl.processor.config.RestTargetProperties
import dev.dnpm.etl.processor.monitoring.ReportService
import dev.dnpm.etl.processor.monitoring.RequestStatus
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.GenderCoding
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.PeriodDate
+import dev.pcvolkmer.mv64e.model.Reference
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
@@ -194,13 +199,13 @@ class RestDipMtbFileSenderTest {
val TEST_REQUEST_ID = RequestId("TestId")
val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
- fun dnpmV2MtbFile(): Mtb {
- return Mtb().apply {
+ fun dnpmV2MtbFile(): PatientRecord {
+ return PatientRecord().apply {
this.patient =
Patient().apply {
this.id = "PID"
this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ this.gender = GenderCoding().apply { this.code = GenderCoding.CodeEnum.MALE }
}
this.episodesOfCare =
listOf(
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
index abc17c6..93c9106 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
@@ -27,7 +27,17 @@ import dev.dnpm.etl.processor.config.JacksonConfig
import dev.dnpm.etl.processor.consent.MtbFileConsentService
import dev.dnpm.etl.processor.services.ConsentProcessor
import dev.dnpm.etl.processor.services.ConsentProcessorTest
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.GenderCoding
+import dev.pcvolkmer.mv64e.model.Msi
+import dev.pcvolkmer.mv64e.model.MtbDiagnosis
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.MtbSystemicTherapy
+import dev.pcvolkmer.mv64e.model.OncoProcedure
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.PeriodDate
+import dev.pcvolkmer.mv64e.model.Reference
+import dev.pcvolkmer.mv64e.model.TumorSpecimen
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.junit.jupiter.api.Nested
@@ -56,12 +66,12 @@ class ExtensionsTest {
val FAKE_MTB_FILE_PATH = "mv64e-mtb-fake-patient.json"
val CLEAN_PATIENT_ID = "644bae7a-56f6-4ee8-b02f-c532e65af5b1"
- private fun fakeMtbFile(): Mtb {
+ private fun fakeMtbFile(): PatientRecord {
val mtbFile = ClassPathResource(FAKE_MTB_FILE_PATH).inputStream
- return getJsonMapper().readValue(mtbFile, Mtb::class.java)
+ return getJsonMapper().readValue(mtbFile, PatientRecord::class.java)
}
- private fun Mtb.serialized(): String {
+ private fun PatientRecord.serialized(): String {
return getJsonMapper().writeValueAsString(this)
}
@@ -80,11 +90,11 @@ class ExtensionsTest {
mtbFile.pseudonymizeWith(pseudonymizeService)
- assertThat(mtbFile.patient.id).isEqualTo("PSEUDO-ID")
+ assertThat(mtbFile.patient?.id).isEqualTo("PSEUDO-ID")
assertThat(mtbFile.serialized()).doesNotContain(CLEAN_PATIENT_ID)
}
- private fun addConsentData(mtbFile: Mtb) {
+ private fun addConsentData(mtbFile: PatientRecord) {
val gIcsConfigProperties = GIcsConfigProperties("", "", "")
val appConfigProperties = AppConfigProperties(emptyList())
@@ -115,12 +125,12 @@ class ExtensionsTest {
doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
val mtbFile =
- Mtb().apply {
+ PatientRecord().apply {
this.patient =
Patient().apply {
this.id = "PID"
this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ this.gender = GenderCoding().apply { this.code = GenderCoding.CodeEnum.MALE }
}
this.episodesOfCare =
listOf(
@@ -136,7 +146,7 @@ class ExtensionsTest {
mtbFile.anonymizeContentWith(pseudonymizeService)
assertThat(mtbFile.episodesOfCare).hasSize(1)
- assertThat(mtbFile.episodesOfCare.map { it.id }).isNotNull
+ assertThat(mtbFile.episodesOfCare?.map { it.id }).isNotNull
}
@Test
@@ -153,20 +163,20 @@ class ExtensionsTest {
val mtbFile = fakeMtbFile()
/** replace hex values with random long, so our test does not match false positives */
- mtbFile.ngsReports.forEach { report ->
- report.results.simpleVariants.forEach { simpleVariant ->
- simpleVariant.externalIds.forEach { extIdValue ->
+ mtbFile.ngsReports?.forEach { report ->
+ report.results.simpleVariants?.forEach { simpleVariant ->
+ simpleVariant.externalIds?.forEach { extIdValue ->
extIdValue.value = Math.random().toLong().toString()
}
}
}
- mtbFile.ngsReports.forEach { report ->
- report.results.rnaFusions.forEach { simpleVariant ->
- simpleVariant.externalIds.forEach { extIdValue ->
+ mtbFile.ngsReports?.forEach { report ->
+ report.results.rnaFusions?.forEach { simpleVariant ->
+ simpleVariant.externalIds?.forEach { extIdValue ->
extIdValue.value = Math.random().toLong().toString()
}
- simpleVariant.fusionPartner3Prime?.transcriptId?.value = Math.random().toLong().toString()
- simpleVariant.fusionPartner5Prime?.transcriptId?.value = Math.random().toLong().toString()
+ simpleVariant.fusionPartner3prime?.transcriptId?.value = Math.random().toLong().toString()
+ simpleVariant.fusionPartner5prime?.transcriptId?.value = Math.random().toLong().toString()
simpleVariant.externalIds?.forEach { it?.value = Math.random().toLong().toString() }
}
}
@@ -203,12 +213,12 @@ class ExtensionsTest {
doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
val mtbFile =
- Mtb().apply {
+ PatientRecord().apply {
this.patient =
Patient().apply {
this.id = "PID"
this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ this.gender = GenderCoding().apply { this.code = GenderCoding.CodeEnum.MALE }
}
this.diagnoses = listOf(MtbDiagnosis().apply { this.id = "Diagnosis-1" })
this.episodesOfCare =
@@ -244,12 +254,12 @@ class ExtensionsTest {
mtbFile.pseudonymizeWith(pseudonymizeService)
mtbFile.anonymizeContentWith(pseudonymizeService)
- assertThat(mtbFile.diagnoses.first().id)
- .isEqualTo(mtbFile.episodesOfCare.first().diagnoses.first().id)
- assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.guidelineTherapies.first().reason.id)
- assertThat(mtbFile.diagnoses.first().id)
- .isEqualTo(mtbFile.guidelineProcedures.first().reason.id)
- assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.specimens.first().diagnosis.id)
+ assertThat(mtbFile.diagnoses?.first()?.id)
+ .isEqualTo(mtbFile.episodesOfCare?.first()?.diagnoses?.first()?.id)
+ assertThat(mtbFile.diagnoses?.first()?.id).isEqualTo(mtbFile.guidelineTherapies?.first()?.reason?.id)
+ assertThat(mtbFile.diagnoses?.first()?.id)
+ .isEqualTo(mtbFile.guidelineProcedures?.first()?.reason?.id)
+ assertThat(mtbFile.diagnoses?.first()?.id).isEqualTo(mtbFile.specimens?.first()?.diagnosis?.id)
}
@Test
@@ -265,12 +275,12 @@ class ExtensionsTest {
doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
val mtbFile =
- Mtb().apply {
+ PatientRecord().apply {
this.patient =
Patient().apply {
this.id = "PID"
this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ this.gender = GenderCoding().apply { this.code = GenderCoding.CodeEnum.MALE }
}
this.msiFindings =
listOf(
@@ -286,10 +296,10 @@ class ExtensionsTest {
mtbFile.anonymizeContentWith(pseudonymizeService)
assertThat(mtbFile.msiFindings).isNotNull
- assertThat(mtbFile.msiFindings[1])
+ assertThat(mtbFile.msiFindings?.get(1))
.satisfiesAnyOf(
- { assertThat(it.id).isNull() },
- { assertThat(it.id).isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098") },
+ { assertThat(it?.id).isNull() },
+ { assertThat(it?.id).isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098") },
)
}
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
index 7c6d6c9..00487d0 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
@@ -21,7 +21,11 @@
package dev.dnpm.etl.processor.pseudonym
import dev.dnpm.etl.processor.config.PseudonymizeConfigProperties
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.PeriodDate
+import dev.pcvolkmer.mv64e.model.Reference
import java.time.Instant
import java.util.*
import org.assertj.core.api.Assertions.assertThat
@@ -37,7 +41,7 @@ import org.mockito.kotlin.whenever
class PseudonymizeServiceTest {
private val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -62,7 +66,7 @@ class PseudonymizeServiceTest {
mtbFile.pseudonymizeWith(pseudonymizeService)
- assertThat(mtbFile.patient.id).isEqualTo("123")
+ assertThat(mtbFile.patient?.id).isEqualTo("123")
}
@Test
@@ -80,7 +84,7 @@ class PseudonymizeServiceTest {
mtbFile.pseudonymizeWith(pseudonymizeService)
- assertThat(mtbFile.patient.id).isEqualTo("UNKNOWN_123")
+ assertThat(mtbFile.patient?.id).isEqualTo("UNKNOWN_123")
}
@Test
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
index a85d555..6cb8c43 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
@@ -27,9 +27,11 @@ import dev.dnpm.etl.processor.config.JacksonConfig
import dev.dnpm.etl.processor.consent.ConsentDomain
import dev.dnpm.etl.processor.consent.GicsConsentService
import dev.dnpm.etl.processor.consent.MtbFileConsentService
-import dev.pcvolkmer.mv64e.mtb.Mtb
-import dev.pcvolkmer.mv64e.mtb.MvhSubmissionType
-import dev.pcvolkmer.mv64e.mtb.Patient
+import dev.pcvolkmer.mv64e.model.BroadConsentReasonMissing
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhSubmissionType
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.CodeableConcept
@@ -46,6 +48,8 @@ import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
import tools.jackson.databind.json.JsonMapper
@@ -99,13 +103,13 @@ class ConsentProcessorTest {
.getConsent(any(), any(), eq(ConsentDomain.MODELLVORHABEN_64E))
val inputMtb =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("d611d429-5003-11f0-a144-661e92ac9503").build())
.build()
val checkResult = consentProcessor.consentGatedCheckAndTryEmbedding(inputMtb)
assertThat(checkResult).isTrue
- assertThat(inputMtb.metadata.researchConsents).isNotEmpty
+ assertThat(inputMtb.metadata?.researchConsents).isNotEmpty
}
@Test
@@ -122,7 +126,7 @@ class ConsentProcessorTest {
assertThat(consentProcessor.toString()).isNotNull
val inputMtb =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("d611d429-5003-11f0-a144-661e92ac9503").build())
.build()
val checkResult = consentProcessor.consentGatedCheckAndTryEmbedding(inputMtb)
@@ -256,15 +260,56 @@ class ConsentProcessorTest {
.getConsent(any(), any(), eq(ConsentDomain.MODELLVORHABEN_64E))
val inputMtb =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("d611d429-5003-11f0-a144-661e92ac9503").build())
.build()
val checkResult = fixture.consentGatedCheckAndTryEmbedding(inputMtb)
assertThat(checkResult).isNotNull
- if (isTestSubmission) assertThat(inputMtb.metadata.type).isEqualTo(MvhSubmissionType.TEST)
+ if (isTestSubmission) assertThat(inputMtb.metadata?.type).isEqualTo(MvhSubmissionType.TEST)
else {
- assertThat(inputMtb.metadata.type).isEqualTo(MvhSubmissionType.INITIAL)
+ assertThat(inputMtb.metadata?.type).isEqualTo(MvhSubmissionType.INITIAL)
}
}
+
+ @Test
+ fun doNotRequestBroadConsentIfReasonMissingIsGiven() {
+ doAnswer { Bundle() }
+ .whenever(gicsConsentService)
+ .getConsent(any(), any(), eq(ConsentDomain.MODELLVORHABEN_64E))
+
+ val inputMtb =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("d611d429-5003-11f0-a144-661e92ac9503").build())
+ .metadata(MvhMetadata.builder().reasonResearchConsentMissing(BroadConsentReasonMissing.OTHER_PATIENT_REASON).build())
+ .build()
+ val checkResult = consentProcessor.consentGatedCheckAndTryEmbedding(inputMtb)
+
+ verify(gicsConsentService, times(1))
+ .getConsent(any(), any(), eq(ConsentDomain.MODELLVORHABEN_64E))
+ verify(gicsConsentService, times(0))
+ .getConsent(any(), any(), eq(ConsentDomain.BROAD_CONSENT))
+
+ assertThat(checkResult).isFalse
+ assertThat(inputMtb.metadata?.researchConsents).isEmpty()
+ }
+
+ @ParameterizedTest
+ @CsvSource(value = ["permittedConsentBundle.json,permit", "deniedConsentBundle.json,deny"])
+ fun checkGetProvisionTypeByPolicyCode(filename: String, expected: String) {
+ val bundle =
+ fhirContext
+ .newJsonParser()
+ .parseResource(this.javaClass.classLoader.getResourceAsStream(filename))
+ assertThat(bundle).isInstanceOf(Bundle::class.java)
+
+ val actual =
+ consentProcessor.getProvisionTypeByPolicyCode(
+ bundle as Bundle,
+ Date(),
+ ConsentDomain.BROAD_CONSENT,
+ )
+
+ assertThat(actual).isEqualTo(Consent.ConsentProvisionType.valueOf(expected.uppercase()))
+ }
}
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 6827a4f..17570d4 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
@@ -20,7 +20,6 @@
package dev.dnpm.etl.processor.services
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.*
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.consent.TtpConsentStatus
@@ -33,9 +32,19 @@ import dev.dnpm.etl.processor.output.DnpmV2MtbFileRequest
import dev.dnpm.etl.processor.output.MtbFileSender
import dev.dnpm.etl.processor.output.RestMtbFileSender
import dev.dnpm.etl.processor.pseudonym.PseudonymizeService
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.ConsentProvisionType
+import dev.pcvolkmer.mv64e.model.FollowUp
+import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose
+import dev.pcvolkmer.mv64e.model.MtbEpisodeOfCare
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner
+import dev.pcvolkmer.mv64e.model.MvhSubmissionType
+import dev.pcvolkmer.mv64e.model.Patient
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.PeriodDate
+import dev.pcvolkmer.mv64e.model.Reference
import org.assertj.core.api.Assertions.assertThat
-import org.hl7.fhir.r4.model.Consent
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
@@ -123,12 +132,12 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -180,12 +189,12 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -241,12 +250,12 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -306,21 +315,21 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.genomDeTan(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(
MvhMetadata.builder()
.modelProjectConsent(
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.PERMIT)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.build()
)
@@ -406,7 +415,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.genomDeTan(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
@@ -423,7 +432,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata())
.episodesOfCare(
@@ -446,8 +455,8 @@ class RequestProcessorTest {
val requestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(requestCaptor.capture())
assertThat(requestCaptor.firstValue).isNotNull
- assertThat(requestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.ADDITION)
- assertThat(requestCaptor.firstValue.content.metadata.transferTan).isEqualTo("f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2")
+ assertThat(requestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.content.metadata?.transferTAN).isEqualTo("f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2")
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -503,10 +512,10 @@ class RequestProcessorTest {
doAnswer { it.arguments.first() }
.whenever(transformationService)
- .transform(any<Mtb>())
+ .transform(any<PatientRecord>())
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata())
.episodesOfCare(
@@ -577,7 +586,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -586,7 +595,7 @@ class RequestProcessorTest {
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -630,7 +639,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.genomDeTan(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
@@ -647,7 +656,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata())
.episodesOfCare(
@@ -772,7 +781,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
@@ -789,7 +798,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.episodesOfCare(
listOf(
@@ -812,6 +821,7 @@ class RequestProcessorTest {
verify(requestService, times(1)).save(requestCaptor.capture())
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.BLOCKED_INITIAL)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
verify(applicationEventPublisher, times(0)).publishEvent(any())
verify(sender, times(0)).send(any<DnpmV2MtbFileRequest>())
@@ -872,7 +882,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -893,7 +903,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
.episodesOfCare(
@@ -918,6 +928,7 @@ class RequestProcessorTest {
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -925,7 +936,7 @@ class RequestProcessorTest {
val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.ADDITION)
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
}
@Test
@@ -983,7 +994,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -1004,7 +1015,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
.episodesOfCare(
@@ -1029,6 +1040,7 @@ class RequestProcessorTest {
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -1036,7 +1048,7 @@ class RequestProcessorTest {
val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.ADDITION)
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
}
@Test
@@ -1081,7 +1093,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -1102,7 +1114,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
.episodesOfCare(
@@ -1127,6 +1139,7 @@ class RequestProcessorTest {
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.INITIAL)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -1134,13 +1147,58 @@ class RequestProcessorTest {
val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.INITIAL)
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.INITIAL)
+ }
+
+ }
+
+ @Nested
+ inner class FollowUpSubmission {
+
+ private lateinit var pseudonymizeService: PseudonymizeService
+ private lateinit var transformationService: TransformationService
+ private lateinit var sender: MtbFileSender
+ private lateinit var requestService: RequestService
+ private lateinit var applicationEventPublisher: ApplicationEventPublisher
+ private lateinit var appConfigProperties: AppConfigProperties
+ private lateinit var consentProcessor: ConsentProcessor
+ private lateinit var requestProcessor: RequestProcessor
+ private lateinit var jsonMapper: JsonMapper
+
+ @BeforeEach
+ fun setup(
+ @Mock pseudonymizeService: PseudonymizeService,
+ @Mock transformationService: TransformationService,
+ @Mock sender: RestMtbFileSender,
+ @Mock requestService: RequestService,
+ @Mock applicationEventPublisher: ApplicationEventPublisher,
+ @Mock consentProcessor: ConsentProcessor,
+ ) {
+ this.pseudonymizeService = pseudonymizeService
+ this.transformationService = transformationService
+ this.sender = sender
+ this.requestService = requestService
+ this.applicationEventPublisher = applicationEventPublisher
+ this.appConfigProperties = AppConfigProperties()
+ this.consentProcessor = consentProcessor
+ this.jsonMapper = JsonMapper()
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ appConfigProperties,
+ consentProcessor,
+ )
}
@Test
fun testShouldSendFollowUpMtbFileIfUnacceptedErrorsAndAcceptedInitialFileWasSent() {
- // One failed attempt and one successful but not accepted
val lastRequests =
listOf(
Request(
@@ -1192,7 +1250,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -1213,7 +1271,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
.episodesOfCare(
@@ -1247,6 +1305,8 @@ class RequestProcessorTest {
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.FOLLOWUP)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -1254,14 +1314,13 @@ class RequestProcessorTest {
val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
}
@Test
fun testShouldSendFollowUpMtbFileAfterAdditionWasSent() {
- // One failed attempt and one successful but not accepted
val lastRequests =
listOf(
Request(
@@ -1313,7 +1372,7 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
.whenever(sender)
@@ -1334,7 +1393,7 @@ class RequestProcessorTest {
)
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.patient(Patient.builder().id("123").build())
.metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
.episodesOfCare(
@@ -1368,6 +1427,8 @@ class RequestProcessorTest {
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.FOLLOWUP)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -1375,133 +1436,709 @@ class RequestProcessorTest {
val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
}
- }
- @Test
- fun testShouldSendAdditionMtbFileAfterFollowUpWasSent() {
+ @Test
+ fun testShouldSendFollowUpMtbFileAfterInitialWasSent() {
- // One failed attempt and one successful but not accepted
- val lastRequests =
- listOf(
- Request(
- 1L,
- randomRequestId(),
- PatientPseudonym("TEST_12345678901"),
- PatientId("P1"),
- Fingerprint("initial"),
- RequestType.MTB_FILE,
- SubmissionType.INITIAL,
- RequestStatus.ERROR,
- Tan.empty(),
- Instant.parse("2026-02-10T09:00:00Z"),
- submissionAccepted = false,
- ),
- Request(
- 2L,
- randomRequestId(),
- PatientPseudonym("TEST_12345678901"),
- PatientId("P1"),
- Fingerprint("initial"),
- RequestType.MTB_FILE,
- SubmissionType.INITIAL,
- RequestStatus.WARNING,
- Tan.empty(),
- Instant.parse("2026-02-11T09:00:00Z"),
- submissionAccepted = true,
- ),
- Request(
- 3L,
- randomRequestId(),
- PatientPseudonym("TEST_12345678901"),
- PatientId("P1"),
- Fingerprint("initial"),
- RequestType.MTB_FILE,
- SubmissionType.FOLLOWUP,
- RequestStatus.WARNING,
- Tan.empty(),
- Instant.parse("2026-05-20T09:00:00Z"),
- submissionAccepted = false,
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ ),
+ Request(
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-05-20T09:00:00Z"),
+ submissionAccepted = true,
+ )
)
- )
- doAnswer { lastRequests }
- .whenever(requestService)
- .allRequestsByPatientPseudonym(anyValueClass())
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] as String }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
- doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
- .whenever(sender)
- .send(any<DnpmV2MtbFileRequest>())
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
- whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
- requestProcessor =
- RequestProcessor(
- pseudonymizeService,
- transformationService,
- sender,
- requestService,
- jsonMapper,
- applicationEventPublisher,
- AppConfigProperties(postInitialSubmissionBlock = true),
- consentProcessor,
- )
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
- val mtbFile =
- Mtb.builder()
- .patient(Patient.builder().id("123").build())
- .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
- .episodesOfCare(
- listOf(
- MtbEpisodeOfCare.builder()
- .id("1")
- .patient(Reference.builder().id("123").build())
- .period(
- PeriodDate.builder()
- .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
- .build()
- )
- .build()
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .followUps(
+ listOf(
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-05-21T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-05-21T00:00:00.00Z")))
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.FOLLOWUP)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
+ }
+
+ @Test
+ fun testShouldSendAdditionMtbFileAfterFollowUpWasSent() {
+
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = 0
+ ),
+ Request(
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-02-11T09:00:00Z"),
+ submissionAccepted = true,
+ followupCount = 0
+ ),
+ Request(
+ 3L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.FOLLOWUP,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-05-20T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = 1
)
)
- .followUps(
- listOf(
- FollowUp.builder()
- .patient(Reference.builder().id("123").build())
- .date(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
- .lastContactDate(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
- .build()
+
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .followUps(
+ listOf(
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(1)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
+ }
+
+ @Test
+ fun testShouldSendAdditionalFollowUpMtbFileAfterAdditionWasSentOnSameDay() {
+
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = 0
+ ),
+ Request(
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-02-11T09:00:00Z"),
+ submissionAccepted = true,
+ followupCount = 0
+ ),
+ Request(
+ 3L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.FOLLOWUP,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-05-20T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = 1
+ ),
+ Request(
+ 4L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.ADDITION,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-06-11T05:41:00Z"),
+ submissionAccepted = false,
+ followupCount = 1
)
)
- .build()
- this.requestProcessor.processMtbFile(mtbFile)
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
- val requestCaptor = argumentCaptor<Request>()
- verify(requestService, times(1)).save(requestCaptor.capture())
- assertThat(requestCaptor.firstValue).isNotNull
- assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
- assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- val eventCaptor = argumentCaptor<ResponseEvent>()
- verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
- assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .followUps(
+ listOf(
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-05-20T00:00:00.00Z")))
+ .build(),
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.FOLLOWUP)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(1)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(2)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.FOLLOWUP)
+ }
+
+ @Test
+ fun testShouldSendAdditionMtbFileWithoutNewHigherFollowUpsCount() {
+
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = -1
+ ),
+ Request(
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-02-11T09:00:00Z"),
+ submissionAccepted = true,
+ followupCount = -1
+ ),
+ Request(
+ 3L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.FOLLOWUP,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-06-11T05:41:00Z"),
+ submissionAccepted = false,
+ followupCount = 1
+ )
+ )
+
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .followUps(
+ listOf(
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(1)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
+ }
+
+ @Test
+ fun testShouldSendInitialMtbFileContainingFollowUpsWithoutSuccessfulInitialSubmission() {
+
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = 0
+ )
+ )
+
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .followUps(
+ listOf(
+ FollowUp.builder()
+ .patient(Reference.builder().id("123").build())
+ .date(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .lastContactDate(Date.from(Instant.parse("2026-06-11T00:00:00.00Z")))
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.INITIAL)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(0)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(1)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.INITIAL)
+ }
- val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
- verify(sender, times(1)).send(sendRequestCaptor.capture())
- assertThat(sendRequestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.ADDITION)
+ @Test
+ fun testShouldSendAdditionMtbFileWithoutFollowUpsAndInitialNegativeCount() {
+
+ val lastRequests =
+ listOf(
+ Request(
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.ERROR,
+ Tan.empty(),
+ Instant.parse("2026-02-10T09:00:00Z"),
+ submissionAccepted = false,
+ followupCount = -1
+ ),
+ Request(
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("initial"),
+ RequestType.MTB_FILE,
+ SubmissionType.INITIAL,
+ RequestStatus.WARNING,
+ Tan.empty(),
+ Instant.parse("2026-02-11T09:00:00Z"),
+ submissionAccepted = true,
+ followupCount = -1
+ ),
+ )
+
+ doAnswer { lastRequests }
+ .whenever(requestService)
+ .allRequestsByPatientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<PatientRecord>())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ jsonMapper,
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ val mtbFile =
+ PatientRecord.builder()
+ .patient(Patient.builder().id("123").build())
+ .metadata(MvhMetadata.builder().type(MvhSubmissionType.INITIAL).build())
+ .episodesOfCare(
+ listOf(
+ MtbEpisodeOfCare.builder()
+ .id("1")
+ .patient(Reference.builder().id("123").build())
+ .period(
+ PeriodDate.builder()
+ .start(Date.from(Instant.parse("2026-01-20T00:00:00.00Z")))
+ .build()
+ )
+ .build()
+ )
+ )
+ .build()
+
+ this.requestProcessor.processMtbFile(mtbFile)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.status).isEqualTo(RequestStatus.UNKNOWN)
+ assertThat(requestCaptor.firstValue.submissionType).isEqualTo(SubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.followupCount).isEqualTo(-1)
+ assertThat(requestCaptor.firstValue.expectedFollowupCount).isEqualTo(0)
+
+ val eventCaptor = argumentCaptor<ResponseEvent>()
+ verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
+ assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
+
+ val sendRequestCaptor = argumentCaptor<DnpmV2MtbFileRequest>()
+ verify(sender, times(1)).send(sendRequestCaptor.capture())
+ assertThat(sendRequestCaptor.firstValue.content.metadata?.type).isEqualTo(MvhSubmissionType.ADDITION)
+ }
}
@Test
fun shouldCatchExceptionsWhenProcessingMtbFileAndSaveError() {
- val invalidMtbFile = Mtb.builder().build()
+ val invalidMtbFile = PatientRecord.builder().build()
val success = this.requestProcessor.processMtbFile(invalidMtbFile)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
index 441f3a9..c7a0af7 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
@@ -115,6 +116,27 @@ class ResponseProcessorTest {
assertThat(captor.firstValue.status).isEqualTo(requestStatus)
}
+ @ParameterizedTest
+ @MethodSource("requestFollowUpCount")
+ fun shoulUpdateFollowUpCountFromExpectedFollowUpCountOnSuccess(requestStatus: RequestStatus, followUpCount: Int, expectedFollowUpCount: Int) {
+ doAnswer {
+ testRequest.followupCount = followUpCount
+ testRequest.expectedFollowupCount = expectedFollowUpCount
+ Optional.of(testRequest)
+ }.whenever(requestService).findByUuid(anyValueClass())
+
+ val event =
+ ResponseEvent(RequestId("TestID1234"), Instant.parse("2023-09-09T00:00:00Z"), requestStatus)
+
+ this.responseProcessor.handleResponseEvent(event)
+
+ val captor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(captor.capture())
+ assertThat(captor.firstValue).isNotNull
+ assertThat(captor.firstValue.status).isEqualTo(requestStatus)
+ assertThat(captor.firstValue.followupCount).isEqualTo(expectedFollowUpCount)
+ }
+
companion object {
@JvmStatic
@@ -126,5 +148,16 @@ class ResponseProcessorTest {
RequestStatus.DUPLICATION,
)
}
+
+ @JvmStatic
+ fun requestFollowUpCount(): Set<Arguments> {
+ return setOf(
+ Arguments.of(RequestStatus.SUCCESS, 1, 2),
+ Arguments.of(RequestStatus.WARNING, 1, 2),
+ Arguments.of(RequestStatus.ERROR, 1, 1),
+ Arguments.of(RequestStatus.DUPLICATION, 1, 1),
+ Arguments.of(RequestStatus.NO_CONSENT, 1, 1),
+ )
+ }
}
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
index 66e45f8..cbca4f7 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
@@ -24,7 +24,15 @@ import ca.uhn.fhir.context.FhirContext
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
import dev.dnpm.etl.processor.config.JacksonConfig
-import dev.pcvolkmer.mv64e.mtb.*
+import dev.pcvolkmer.mv64e.model.Coding
+import dev.pcvolkmer.mv64e.model.ConsentProvisionType
+import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose
+import dev.pcvolkmer.mv64e.model.MtbDiagnosis
+import dev.pcvolkmer.mv64e.model.MvhMetadata
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent
+import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner
+import dev.pcvolkmer.mv64e.model.PatientRecord
+import dev.pcvolkmer.mv64e.model.ResearchConsent
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -49,7 +57,7 @@ class TransformationServiceTest {
@Test
fun shouldTransformMtbFile() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.diagnoses(
listOf(
MtbDiagnosis.builder()
@@ -63,13 +71,13 @@ class TransformationServiceTest {
val actual = this.service.transform(mtbFile)
assertThat(actual).isNotNull
- assertThat(actual.diagnoses[0].code.version).isEqualTo("2014")
+ assertThat(actual.diagnoses!![0].code.version).isEqualTo("2014")
}
@Test
fun shouldOnlyTransformGivenValues() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.diagnoses(
listOf(
MtbDiagnosis.builder()
@@ -87,16 +95,16 @@ class TransformationServiceTest {
val actual = this.service.transform(mtbFile)
assertThat(actual).isNotNull
- assertThat(actual.diagnoses[0].code.code).isEqualTo("F79.9")
- assertThat(actual.diagnoses[0].code.version).isEqualTo("2014")
- assertThat(actual.diagnoses[1].code.code).isEqualTo("F79.8")
- assertThat(actual.diagnoses[1].code.version).isEqualTo("2019")
+ assertThat(actual.diagnoses!![0].code.code).isEqualTo("F79.9")
+ assertThat(actual.diagnoses!![0].code.version).isEqualTo("2014")
+ assertThat(actual.diagnoses!![1].code.code).isEqualTo("F79.8")
+ assertThat(actual.diagnoses!![1].code.version).isEqualTo("2019")
}
@Test
fun shouldTransformConsentValues() {
val mtbFile =
- Mtb.builder()
+ PatientRecord.builder()
.diagnoses(
listOf(
MtbDiagnosis.builder()
@@ -114,35 +122,35 @@ class TransformationServiceTest {
val actual = this.service.transform(mtbFile)
assertThat(actual).isNotNull
- assertThat(actual.diagnoses[0].code.code).isEqualTo("F79.9")
- assertThat(actual.diagnoses[0].code.version).isEqualTo("2014")
- assertThat(actual.diagnoses[1].code.code).isEqualTo("F79.8")
- assertThat(actual.diagnoses[1].code.version).isEqualTo("2019")
+ assertThat(actual.diagnoses!![0].code.code).isEqualTo("F79.9")
+ assertThat(actual.diagnoses!![0].code.version).isEqualTo("2014")
+ assertThat(actual.diagnoses!![1].code.code).isEqualTo("F79.8")
+ assertThat(actual.diagnoses!![1].code.version).isEqualTo("2019")
}
@Test
fun shouldTransformConsent() {
- val mvhMetadata = MvhMetadata.builder().transferTan("transfertan12345").build()
+ val mvhMetadata = MvhMetadata.builder().transferTAN("transfertan12345").build()
assertThat(mvhMetadata).isNotNull
mvhMetadata.modelProjectConsent =
- ModelProjectConsent.builder()
+ MvhMetadataModelProjectConsent.builder()
.date(Date.from(Instant.parse("2025-08-15T00:00:00.00Z")))
.version("1")
.provisions(
listOf(
- Provision.builder()
- .type(ConsentProvision.PERMIT)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.SEQUENCING)
.date(Date.from(Instant.parse("2025-08-15T00:00:00.00Z")))
.build(),
- Provision.builder()
- .type(ConsentProvision.PERMIT)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.PERMIT)
.purpose(ModelProjectConsentPurpose.REIDENTIFICATION)
.date(Date.from(Instant.parse("2025-08-15T00:00:00.00Z")))
.build(),
- Provision.builder()
- .type(ConsentProvision.DENY)
+ MvhMetadataModelProjectConsentProvisionsInner.builder()
+ .type(ConsentProvisionType.DENY)
.purpose(ModelProjectConsentPurpose.CASE_IDENTIFICATION)
.date(Date.from(Instant.parse("2025-08-15T00:00:00.00Z")))
.build(),
@@ -158,11 +166,11 @@ class TransformationServiceTest {
)
mvhMetadata.researchConsents = mutableListOf()
- mvhMetadata.researchConsents.add(MvhMetadata.ResearchConsent.from(jsonNode))
+ mvhMetadata.researchConsents?.add(ResearchConsent.from(jsonNode))
- val mtbFile = Mtb.builder().metadata(mvhMetadata).build()
+ val mtbFile = PatientRecord.builder().metadata(mvhMetadata).build()
val transformed = service.transform(mtbFile)
- assertThat(transformed.metadata.modelProjectConsent.date).isNotNull
+ assertThat(transformed.metadata?.modelProjectConsent?.date).isNotNull
}
}