summaryrefslogtreecommitdiff
path: root/src/test/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/kotlin')
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt92
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt50
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt28
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/helpers.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt22
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt20
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt24
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt31
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt490
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt451
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt32
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt40
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt33
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt9
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt15
23 files changed, 809 insertions, 555 deletions
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
index 716529b..95ef0d4 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2026 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * 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
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
new file mode 100644
index 0000000..b940537
--- /dev/null
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.config
+
+import com.fasterxml.jackson.databind.node.ObjectNode
+import dev.pcvolkmer.mv64e.mtb.Mtb
+import dev.pcvolkmer.mv64e.mtb.MvhMetadata
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
+import java.util.*
+
+class Jackson3ConfigTest {
+
+ lateinit var jacksonConfig: JacksonConfig
+
+ @BeforeEach
+ fun setup() {
+ this.jacksonConfig = JacksonConfig()
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [
+ "mv64e-mtb-fake-patient.json",
+ "fake_broadConsent_mii_response_deny.json",
+ "fake_broadConsent_mii_response_permit.json",
+ ])
+ fun shouldSerializeJsonWithoutNulledOutFields(filename: String) {
+ val inputJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
+
+ val jsonNode = this.jacksonConfig.jsonMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(jsonNode)
+
+ assertThat(actual).doesNotContain("null")
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [
+ "fake_broadConsent_mii_response_deny.json",
+ "fake_broadConsent_mii_response_permit.json",
+ ])
+ fun shouldSerializeConsentWithoutWithoutDatesAsTimestamps(filename: String) {
+ val inputJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
+
+ val json = this.jacksonConfig.jsonMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(json)
+
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ }
+
+ @Test
+ fun shouldSerializeJsonWithBroadConsent() {
+ val inputMtbFileJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("mv64e-mtb-fake-patient.json"))?.readAllBytes()?.decodeToString()
+
+ 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)
+ // 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()
+
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(mtb)
+
+ assertThat(actual).doesNotContain("null")
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ assertThat(actual).contains("""{"entry":[{"fullUrl":"http://localhost:8080/ttp-fhir/fhir/gics/Consent/7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd"""")
+ }
+}
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 9042d8c..e734c6f 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
@@ -1,5 +1,28 @@
+/*
+ * 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.config
+import com.fasterxml.jackson.databind.node.ObjectNode
+import dev.pcvolkmer.mv64e.mtb.Mtb
+import dev.pcvolkmer.mv64e.mtb.MvhMetadata
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -9,11 +32,11 @@ import java.util.*
class JacksonConfigTest {
- lateinit var jacksonConfig: JacksonConfig
+ lateinit var jacksonConfig: Jackson2Config
@BeforeEach
fun setup() {
- this.jacksonConfig = JacksonConfig()
+ this.jacksonConfig = Jackson2Config()
}
@ParameterizedTest
@@ -26,8 +49,8 @@ class JacksonConfigTest {
val inputJson =
Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
- val json = this.jacksonConfig.objectMapper().readTree(inputJson)
- val actual = this.jacksonConfig.objectMapper().writeValueAsString(json)
+ val jsonNode = this.jacksonConfig.objectMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.objectMapper().writeValueAsString(jsonNode)
assertThat(actual).doesNotContain("null")
}
@@ -47,4 +70,23 @@ class JacksonConfigTest {
assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
}
+ @Test
+ fun shouldSerializeJsonWithBroadConsent() {
+ val inputMtbFileJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("mv64e-mtb-fake-patient.json"))?.readAllBytes()?.decodeToString()
+
+ 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 consentJsonNode = this.jacksonConfig.objectMapper().readTree(inputConsentJson)
+ mtb.metadata = MvhMetadata.builder().researchConsents(listOf(MvhMetadata.ResearchConsent.from(consentJsonNode as ObjectNode))).build()
+
+ val actual = this.jacksonConfig.objectMapper().writeValueAsString(mtb)
+
+ assertThat(actual).doesNotContain("null")
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ assertThat(actual).contains("""{"entry":[{"fullUrl":"http://localhost:8080/ttp-fhir/fhir/gics/Consent/7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd"""")
+ }
+
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
index 1140425..30e3823 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
@@ -1,11 +1,29 @@
+/*
+ * 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 com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.services.ConsentProcessor
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Consent
@@ -15,13 +33,15 @@ 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 objectMapper = ObjectMapper()
+ val jsonMapper = JsonMapper()
val fhirContext = FhirContext.forR4()
@BeforeEach
@@ -33,7 +53,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
consentService,
)
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 85a8b3e..284c552 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-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
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
index b7bf436..192bf90 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-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
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 0d3f275..eeb6288 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-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
@@ -43,13 +44,14 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.firstValue
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
+import tools.jackson.databind.json.JsonMapper
import java.util.*
@ExtendWith(MockitoExtension::class)
class KafkaInputListenerTest {
private lateinit var requestProcessor: RequestProcessor
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var kafkaInputListener: KafkaInputListener
@@ -59,9 +61,9 @@ class KafkaInputListenerTest {
@Mock consentEvaluator: ConsentEvaluator,
) {
this.requestProcessor = requestProcessor
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
- this.kafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, objectMapper)
+ this.kafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, jsonMapper)
}
@Test
@@ -88,7 +90,7 @@ class KafkaInputListenerTest {
.build()
kafkaInputListener.onMessage(
- ConsumerRecord("testtopic", 0, 0, "", this.objectMapper.writeValueAsString(mtbFile))
+ ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
@@ -113,7 +115,7 @@ class KafkaInputListenerTest {
.build()
kafkaInputListener.onMessage(
- ConsumerRecord("testtopic", 0, 0, "", this.objectMapper.writeValueAsString(mtbFile))
+ ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
}
@@ -153,7 +155,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -197,7 +199,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -248,7 +250,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -303,7 +305,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
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 c8e5804..9ee4b2b 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-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
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
index a380d2a..62ece6c 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
@@ -1,3 +1,23 @@
+/*
+ * 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.monitoring
import dev.dnpm.etl.processor.config.GIcsConfigProperties
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
index 74d1138..83c2354 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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.monitoring
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -12,8 +32,8 @@ class ReportServiceTest {
@BeforeEach
fun setUp() {
- val jacksonConfig = JacksonConfig()
- service = ReportService(jacksonConfig.objectMapper())
+ val jackson3Config = JacksonConfig()
+ service = ReportService(jackson3Config.jsonMapper())
}
@Test
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 ac14366..ee840a8 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-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
@@ -19,17 +20,12 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.CustomMediaType
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 java.time.Instant
-import java.util.*
-import java.util.concurrent.CompletableFuture.completedFuture
-import java.util.concurrent.ExecutionException
import org.apache.kafka.clients.producer.ProducerRecord
import org.apache.kafka.clients.producer.RecordMetadata
import org.apache.kafka.common.TopicPartition
@@ -47,6 +43,11 @@ import org.springframework.kafka.core.KafkaTemplate
import org.springframework.kafka.support.SendResult
import org.springframework.retry.policy.SimpleRetryPolicy
import org.springframework.retry.support.RetryTemplateBuilder
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
+import java.util.concurrent.CompletableFuture.completedFuture
+import java.util.concurrent.ExecutionException
@ExtendWith(MockitoExtension::class)
class KafkaMtbFileSenderTest {
@@ -58,18 +59,18 @@ class KafkaMtbFileSenderTest {
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(@Mock kafkaTemplate: KafkaTemplate<String, String>) {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper.builder().build()
this.kafkaTemplate = kafkaTemplate
this.kafkaMtbFileSender =
- KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
+ KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, jsonMapper)
}
@ParameterizedTest
@@ -94,7 +95,7 @@ class KafkaMtbFileSenderTest {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.kafkaMtbFileSender =
- KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
+ KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.jsonMapper)
doAnswer {
if (null != testData.exception) {
@@ -126,18 +127,18 @@ class KafkaMtbFileSenderTest {
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(@Mock kafkaTemplate: KafkaTemplate<String, String>) {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
this.kafkaTemplate = kafkaTemplate
this.kafkaMtbFileSender =
- KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
+ KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, jsonMapper)
}
@ParameterizedTest
@@ -179,7 +180,7 @@ class KafkaMtbFileSenderTest {
.isEqualTo("POST".toByteArray())
assertThat(captor.firstValue.value()).isNotNull
assertThat(captor.firstValue.value())
- .isEqualTo(objectMapper.writeValueAsString(dnmpV2kafkaRecordData(TEST_REQUEST_ID)))
+ .isEqualTo(jsonMapper.writeValueAsString(dnmpV2kafkaRecordData(TEST_REQUEST_ID)))
}
@Test
@@ -212,7 +213,7 @@ class KafkaMtbFileSenderTest {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.kafkaMtbFileSender =
- KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
+ KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.jsonMapper)
doAnswer {
if (null != testData.exception) {
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 2ab0218..d95ced0 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientPseudonym
import dev.dnpm.etl.processor.RequestId
@@ -30,8 +29,6 @@ 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 java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
@@ -48,252 +45,255 @@ import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
import org.springframework.web.client.RestTemplate
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
class RestDipMtbFileSenderTest {
- @Nested
- inner class DnpmV2ContentRequest {
-
- private lateinit var mockRestServiceServer: MockRestServiceServer
-
- private lateinit var restMtbFileSender: RestMtbFileSender
-
- private var reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
-
- @BeforeEach
- fun setup() {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
-
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
-
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
- }
+ @Nested
+ inner class DnpmV2ContentRequest {
+
+ private lateinit var mockRestServiceServer: MockRestServiceServer
+
+ private lateinit var restMtbFileSender: RestMtbFileSender
+
+ private var reportService =
+ ReportService(JsonMapper())
+
+ @BeforeEach
+ fun setup() {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#mtbFileRequestWithResponseSource"
+ )
+ fun shouldReturnExpectedResponseForDnpmV2MtbFilePost(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
+ .andExpect(
+ header(
+ HttpHeaders.CONTENT_TYPE,
+ CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE,
+ )
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#mtbFileRequestWithResponseSource"
- )
- fun shouldReturnExpectedResponseForDnpmV2MtbFilePost(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer
- .expect(method(HttpMethod.POST))
- .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
- .andExpect(
- header(
- HttpHeaders.CONTENT_TYPE,
- CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE,
- )
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ val response = restMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
}
- }
-
- @Nested
- inner class DeleteRequest {
- private lateinit var mockRestServiceServer: MockRestServiceServer
-
- private lateinit var restMtbFileSender: RestMtbFileSender
-
- private var reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
-
- @BeforeEach
- fun setup() {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+ @Nested
+ inner class DeleteRequest {
+
+ private lateinit var mockRestServiceServer: MockRestServiceServer
+
+ private lateinit var restMtbFileSender: RestMtbFileSender
+
+ private var reportService =
+ ReportService(JsonMapper())
+
+ @BeforeEach
+ fun setup() {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
+ )
+ fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.DELETE))
+ .andExpect(
+ requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
+ )
+ fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties())
+ retryTemplate.setBackOffPolicy(NoBackOffPolicy())
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+
+ val expectedCount =
+ when (requestWithResponse.httpStatus) {
+ // OK - No Retry
+ HttpStatus.OK,
+ HttpStatus.CREATED,
+ HttpStatus.UNPROCESSABLE_ENTITY,
+ HttpStatus.BAD_REQUEST -> ExpectedCount.max(1)
+ // Request failed - Retry max 3 times
+ else -> ExpectedCount.max(3)
+ }
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
- }
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.DELETE))
+ .andExpect(
+ requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
- )
- fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer
- .expect(method(HttpMethod.DELETE))
- .andExpect(
- requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
}
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
- )
- fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties())
- retryTemplate.setBackOffPolicy(NoBackOffPolicy())
-
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
-
- val expectedCount =
- when (requestWithResponse.httpStatus) {
- // OK - No Retry
- HttpStatus.OK,
- HttpStatus.CREATED,
- HttpStatus.UNPROCESSABLE_ENTITY,
- HttpStatus.BAD_REQUEST -> ExpectedCount.max(1)
- // Request failed - Retry max 3 times
- else -> ExpectedCount.max(3)
- }
-
- this.mockRestServiceServer
- .expect(expectedCount, method(HttpMethod.DELETE))
- .andExpect(
- requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
- }
- }
-
- companion object {
- data class RequestWithResponse(
- val httpStatus: HttpStatus,
- val body: String,
- val response: MtbFileSender.Response,
- )
-
- val TEST_REQUEST_ID = RequestId("TestId")
- val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
-
- fun dnpmV2MtbFile(): Mtb {
- return Mtb().apply {
- this.patient =
- dev.pcvolkmer.mv64e.mtb.Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ companion object {
+ data class RequestWithResponse(
+ val httpStatus: HttpStatus,
+ val body: String,
+ val response: MtbFileSender.Response,
+ )
+
+ val TEST_REQUEST_ID = RequestId("TestId")
+ val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
+
+ fun dnpmV2MtbFile(): Mtb {
+ return Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "1"
+ this.patient = Reference().apply { this.id = "PID" }
+ this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
+ }
+ )
}
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "1"
- this.patient = Reference().apply { this.id = "PID" }
- this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
- }
+ }
+
+ private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
+
+ /**
+ * Synthetic http responses with related request status Also see:
+ * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun mtbFileRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(
+ HttpStatus.OK,
+ responseBodyWithMaxSeverity(ReportService.Severity.INFO),
+ MtbFileSender.Response(
+ RequestStatus.SUCCESS,
+ responseBodyWithMaxSeverity(ReportService.Severity.INFO),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.CREATED,
+ responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
+ MtbFileSender.Response(
+ RequestStatus.WARNING,
+ responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.BAD_REQUEST,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ MtbFileSender.Response(
+ RequestStatus.ERROR,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.UNPROCESSABLE_ENTITY,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ MtbFileSender.Response(
+ RequestStatus.ERROR,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ ),
+ ),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
)
- }
- }
-
- private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
-
- /**
- * Synthetic http responses with related request status Also see:
- * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
- */
- @JvmStatic
- fun mtbFileRequestWithResponseSource(): Set<RequestWithResponse> {
- return setOf(
- RequestWithResponse(
- HttpStatus.OK,
- responseBodyWithMaxSeverity(ReportService.Severity.INFO),
- MtbFileSender.Response(
- RequestStatus.SUCCESS,
- responseBodyWithMaxSeverity(ReportService.Severity.INFO),
- ),
- ),
- RequestWithResponse(
- HttpStatus.CREATED,
- responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
- MtbFileSender.Response(
- RequestStatus.WARNING,
- responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
- ),
- ),
- RequestWithResponse(
- HttpStatus.BAD_REQUEST,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- MtbFileSender.Response(
- RequestStatus.ERROR,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- ),
- ),
- RequestWithResponse(
- HttpStatus.UNPROCESSABLE_ENTITY,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- MtbFileSender.Response(
- RequestStatus.ERROR,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- ),
- ),
- // Some more errors not mentioned in documentation
- RequestWithResponse(
- HttpStatus.NOT_FOUND,
- ERROR_RESPONSE_BODY,
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- RequestWithResponse(
- HttpStatus.INTERNAL_SERVER_ERROR,
- ERROR_RESPONSE_BODY,
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- )
- }
-
- /**
- * Synthetic http responses with related request status Also see:
- * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
- */
- @JvmStatic
- fun deleteRequestWithResponseSource(): Set<RequestWithResponse> {
- return setOf(
- RequestWithResponse(HttpStatus.OK, "", MtbFileSender.Response(RequestStatus.SUCCESS)),
- // Some more errors not mentioned in documentation
- RequestWithResponse(
- HttpStatus.NOT_FOUND,
- "what????",
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- RequestWithResponse(
- HttpStatus.INTERNAL_SERVER_ERROR,
- "what????",
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- )
- }
+ }
+
+ /**
+ * Synthetic http responses with related request status Also see:
+ * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun deleteRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(HttpStatus.OK, "", MtbFileSender.Response(RequestStatus.SUCCESS)),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ )
+ }
- fun responseBodyWithMaxSeverity(severity: ReportService.Severity): String {
- return when (severity) {
- ReportService.Severity.INFO ->
- """
+ fun responseBodyWithMaxSeverity(severity: ReportService.Severity): String {
+ return when (severity) {
+ ReportService.Severity.INFO ->
+ """
{
"patient": "PID",
"issues": [
@@ -302,8 +302,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.WARNING ->
- """
+ ReportService.Severity.WARNING ->
+ """
{
"patient": "PID",
"issues": [
@@ -313,8 +313,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.ERROR ->
- """
+ ReportService.Severity.ERROR ->
+ """
{
"patient": "PID",
"issues": [
@@ -325,8 +325,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.FATAL ->
- """
+ ReportService.Severity.FATAL ->
+ """
{
"patient": "PID",
"issues": [
@@ -337,7 +337,7 @@ class RestDipMtbFileSenderTest {
]
}
"""
- }
+ }
+ }
}
- }
}
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 84b081a..abc17c6 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-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
@@ -20,7 +21,6 @@
package dev.dnpm.etl.processor.pseudonym
import ca.uhn.fhir.context.FhirContext
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -28,8 +28,6 @@ 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 java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.junit.jupiter.api.Nested
@@ -42,253 +40,256 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
@ExtendWith(MockitoExtension::class)
class ExtensionsTest {
- fun getObjectMapper(): ObjectMapper {
- return JacksonConfig().objectMapper()
- }
+ fun getJsonMapper(): JsonMapper {
+ return JacksonConfig().jsonMapper()
+ }
- @Nested
- inner class UsingDnpmV2Datamodel {
+ @Nested
+ inner class UsingDnpmV2Datamodel {
- val FAKE_MTB_FILE_PATH = "mv64e-mtb-fake-patient.json"
- val CLEAN_PATIENT_ID = "644bae7a-56f6-4ee8-b02f-c532e65af5b1"
+ val FAKE_MTB_FILE_PATH = "mv64e-mtb-fake-patient.json"
+ val CLEAN_PATIENT_ID = "644bae7a-56f6-4ee8-b02f-c532e65af5b1"
- private fun fakeMtbFile(): Mtb {
- val mtbFile = ClassPathResource(FAKE_MTB_FILE_PATH).inputStream
- return getObjectMapper().readValue(mtbFile, Mtb::class.java)
- }
+ private fun fakeMtbFile(): Mtb {
+ val mtbFile = ClassPathResource(FAKE_MTB_FILE_PATH).inputStream
+ return getJsonMapper().readValue(mtbFile, Mtb::class.java)
+ }
- private fun Mtb.serialized(): String {
- return getObjectMapper().writeValueAsString(this)
- }
+ private fun Mtb.serialized(): String {
+ return getJsonMapper().writeValueAsString(this)
+ }
- @Test
- fun shouldNotContainCleanPatientId(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
+ @Test
+ fun shouldNotContainCleanPatientId(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- val mtbFile = fakeMtbFile()
- mtbFile.ensureMetaDataIsInitialized()
- addConsentData(mtbFile)
+ val mtbFile = fakeMtbFile()
+ mtbFile.ensureMetaDataIsInitialized()
+ addConsentData(mtbFile)
- mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.pseudonymizeWith(pseudonymizeService)
- assertThat(mtbFile.patient.id).isEqualTo("PSEUDO-ID")
- assertThat(mtbFile.serialized()).doesNotContain(CLEAN_PATIENT_ID)
- }
+ assertThat(mtbFile.patient.id).isEqualTo("PSEUDO-ID")
+ assertThat(mtbFile.serialized()).doesNotContain(CLEAN_PATIENT_ID)
+ }
- private fun addConsentData(mtbFile: Mtb) {
- val gIcsConfigProperties = GIcsConfigProperties("", "", "")
- val appConfigProperties = AppConfigProperties(emptyList())
-
- val bundle = Bundle()
- val dummyConsent = ConsentProcessorTest.getDummyGenomDeConsent()
- dummyConsent.patient.reference = "Patient/$CLEAN_PATIENT_ID"
- bundle.addEntry().resource = dummyConsent
-
- ConsentProcessor(
- appConfigProperties,
- gIcsConfigProperties,
- JacksonConfig().objectMapper(),
- FhirContext.forR4(),
- MtbFileConsentService(),
- )
- .embedBroadConsentResources(mtbFile, bundle)
- }
+ private fun addConsentData(mtbFile: Mtb) {
+ val gIcsConfigProperties = GIcsConfigProperties("", "", "")
+ val appConfigProperties = AppConfigProperties(emptyList())
+
+ val bundle = Bundle()
+ val dummyConsent = ConsentProcessorTest.getDummyGenomDeConsent()
+ dummyConsent.patient.reference = "Patient/$CLEAN_PATIENT_ID"
+ bundle.addEntry().resource = dummyConsent
+
+ ConsentProcessor(
+ appConfigProperties,
+ gIcsConfigProperties,
+ JacksonConfig().jsonMapper(),
+ FhirContext.forR4(),
+ MtbFileConsentService(),
+ )
+ .embedBroadConsentResources(mtbFile, bundle)
+ }
- @Test
- fun shouldNotThrowExceptionOnNullValues(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ @Test
+ fun shouldNotThrowExceptionOnNullValues(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "1"
+ this.patient = Reference().apply { this.id = "PID" }
+ this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
+ }
+ )
}
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "1"
- this.patient = Reference().apply { this.id = "PID" }
- this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
- }
- )
- }
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
- assertThat(mtbFile.episodesOfCare).hasSize(1)
- assertThat(mtbFile.episodesOfCare.map { it.id }).isNotNull
- }
+ assertThat(mtbFile.episodesOfCare).hasSize(1)
+ assertThat(mtbFile.episodesOfCare.map { it.id }).isNotNull
+ }
- @Test
- fun shouldNotContainAnyUuidAfterRehashingOfIds(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
+ @Test
+ fun shouldNotContainAnyUuidAfterRehashingOfIds(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
- val mtbFile = fakeMtbFile()
+ 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 ->
- extIdValue.value = Math.random().toLong().toString()
- }
- }
- }
- 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.externalIds?.forEach { it?.value = Math.random().toLong().toString() }
+ /** 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 ->
+ extIdValue.value = Math.random().toLong().toString()
+ }
+ }
+ }
+ 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.externalIds?.forEach { it?.value = Math.random().toLong().toString() }
+ }
+ }
+
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
+
+ val pattern =
+ "\"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\"".toRegex().toPattern()
+ val input = mtbFile.serialized()
+ val matcher = pattern.matcher(input)
+
+ assertThrows<IllegalStateException> {
+ matcher.find()
+ val posSt = "check at pos: " + matcher.start().toString() + ", " + matcher.end()
+ println(posSt + " with " + matcher.group())
+ }
+ .also { assertThat(it.message).isEqualTo("No match found") }
}
- }
-
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
-
- val pattern =
- "\"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\"".toRegex().toPattern()
- val input = mtbFile.serialized()
- val matcher = pattern.matcher(input)
-
- assertThrows<IllegalStateException> {
- matcher.find()
- val posSt = "check at pos: " + matcher.start().toString() + ", " + matcher.end()
- println(posSt + " with " + matcher.group())
- }
- .also { assertThat(it.message).isEqualTo("No match found") }
}
- }
- @Test
- fun shouldUseSameAnonymIdForDiagnosisAndDiagnosisReferences(
- @Mock pseudonymizeService: PseudonymizeService
- ) {
+ @Test
+ fun shouldUseSameAnonymIdForDiagnosisAndDiagnosisReferences(
+ @Mock pseudonymizeService: PseudonymizeService
+ ) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
- }
- this.diagnoses = listOf(MtbDiagnosis().apply { this.id = "Diagnosis-1" })
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "Episode-1"
- this.diagnoses = listOf(Reference().apply { this.id = "Diagnosis-1" })
- }
- )
- this.guidelineTherapies =
- listOf(
- MtbSystemicTherapy().apply {
- this.id = "Systemic-Therapy-1"
- this.reason = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
- this.guidelineProcedures =
- listOf(
- OncoProcedure().apply {
- this.id = "Onco-Procedure-1"
- this.reason = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
- this.specimens =
- listOf(
- TumorSpecimen().apply {
- this.id = "Specimen-1"
- this.diagnosis = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
}
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.diagnoses = listOf(MtbDiagnosis().apply { this.id = "Diagnosis-1" })
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "Episode-1"
+ this.diagnoses = listOf(Reference().apply { this.id = "Diagnosis-1" })
+ }
+ )
+ this.guidelineTherapies =
+ listOf(
+ MtbSystemicTherapy().apply {
+ this.id = "Systemic-Therapy-1"
+ this.reason = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ this.guidelineProcedures =
+ listOf(
+ OncoProcedure().apply {
+ this.id = "Onco-Procedure-1"
+ this.reason = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ this.specimens =
+ listOf(
+ TumorSpecimen().apply {
+ this.id = "Specimen-1"
+ this.diagnosis = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ }
+
+ 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)
+ }
- 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)
- }
-
- @Test
- fun shouldNotThrowAnyExceptionOnMissingMsiId(@Mock pseudonymizeService: PseudonymizeService) {
+ @Test
+ fun shouldNotThrowAnyExceptionOnMissingMsiId(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
- }
- this.msiFindings =
- listOf(
- null,
- Msi.builder().id("1").build(),
- Msi.builder().build(),
- Msi.builder().specimen(null).build(),
- Msi.builder().specimen(Reference.builder().build()).build(),
- )
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
}
-
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
-
- assertThat(mtbFile.msiFindings).isNotNull
- assertThat(mtbFile.msiFindings[1])
- .satisfiesAnyOf(
- { assertThat(it.id).isNull() },
- { assertThat(it.id).isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098") },
- )
- }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.msiFindings =
+ listOf(
+ null,
+ Msi.builder().id("1").build(),
+ Msi.builder().build(),
+ Msi.builder().specimen(null).build(),
+ Msi.builder().specimen(Reference.builder().build()).build(),
+ )
+ }
+
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
+
+ assertThat(mtbFile.msiFindings).isNotNull
+ assertThat(mtbFile.msiFindings[1])
+ .satisfiesAnyOf(
+ { 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 7da0247..7c6d6c9 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
index e9a1650..18e0bb5 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-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
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
index 7743069..2a5a481 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-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
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 331a816..a85d555 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
@@ -1,7 +1,26 @@
+/*
+ * 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.services
import ca.uhn.fhir.context.FhirContext
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -29,6 +48,7 @@ import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
+import tools.jackson.databind.json.JsonMapper
import java.io.IOException
import java.io.InputStream
import java.time.Instant
@@ -40,7 +60,7 @@ class ConsentProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var gicsConsentService: GicsConsentService
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var gIcsConfigProperties: GIcsConfigProperties
private lateinit var fhirContext: FhirContext
private lateinit var consentProcessor: ConsentProcessor
@@ -52,7 +72,7 @@ class ConsentProcessorTest {
this.gIcsConfigProperties = GIcsConfigProperties(uri = "https://gics.example.com", genomDeConsentDomainName = "GenomDE_MV")
val jacksonConfig = JacksonConfig()
- this.objectMapper = jacksonConfig.objectMapper()
+ this.jsonMapper = jacksonConfig.jsonMapper()
this.fhirContext = JacksonConfig.fhirContext()
this.gicsConsentService = gicsConsentService
this.appConfigProperties = AppConfigProperties(emptyList())
@@ -60,7 +80,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
gicsConsentService,
)
@@ -94,7 +114,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
MtbFileConsentService(),
)
@@ -220,7 +240,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
gicsConsentService,
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
index 4308fed..e9c3107 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.services
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.monitoring.ReportService
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.monitoring.asRequestStatus
@@ -30,6 +29,8 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.module.kotlin.KotlinModule
class ReportServiceTest {
private lateinit var reportService: ReportService
@@ -37,7 +38,7 @@ class ReportServiceTest {
@BeforeEach
fun setup() {
this.reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
+ ReportService(JsonMapper.builder().addModule(KotlinModule.Builder().build()).build())
}
@Test
@@ -59,13 +60,34 @@ class ReportServiceTest {
assertThat(actual).hasSize(4)
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.FATAL)
- assertThat(actual[0].message).isEqualTo("Fatal Message")
+ assertThat(actual[0].getMessage()).isEqualTo("Fatal Message")
assertThat(actual[1].severity).isEqualTo(ReportService.Severity.ERROR)
- assertThat(actual[1].message).isEqualTo("Error Message")
+ assertThat(actual[1].getMessage()).isEqualTo("Error Message")
assertThat(actual[2].severity).isEqualTo(ReportService.Severity.WARNING)
- assertThat(actual[2].message).isEqualTo("Warning Message")
+ assertThat(actual[2].getMessage()).isEqualTo("Warning Message")
assertThat(actual[3].severity).isEqualTo(ReportService.Severity.INFO)
- assertThat(actual[3].message).isEqualTo("Info Message")
+ assertThat(actual[3].getMessage()).isEqualTo("Info Message")
+
+ assertThat(actual.asRequestStatus()).isEqualTo(RequestStatus.ERROR)
+ }
+
+ @Test
+ fun shouldParseDataQualityReportWithMissingPathError() {
+ val json =
+ """
+ {
+ "patient": "4711",
+ "issues": [
+ { "severity": "error", "details": "/specimens(0)/type/code: error.path.missing" }
+ ]
+ }
+ """.trimIndent()
+
+ val actual = this.reportService.deserialize(json)
+
+ assertThat(actual).hasSize(1)
+ assertThat(actual[0].severity).isEqualTo(ReportService.Severity.ERROR)
+ assertThat(actual[0].getMessage()).isEqualTo("/specimens(0)/type/code: error.path.missing")
assertThat(actual.asRequestStatus()).isEqualTo(RequestStatus.ERROR)
}
@@ -88,7 +110,7 @@ class ReportServiceTest {
assertThat(actual).hasSize(1)
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.ERROR)
- assertThat(actual[0].message).isEqualTo("Not parsable data quality report '$invalidResponse'")
+ assertThat(actual[0].getMessage()).isEqualTo("Not parsable data quality report '$invalidResponse'")
}
companion object {
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 b51aed2..5a89c03 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
@@ -34,6 +35,7 @@ import dev.dnpm.etl.processor.output.RestMtbFileSender
import dev.dnpm.etl.processor.pseudonym.PseudonymizeService
import dev.pcvolkmer.mv64e.mtb.*
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
@@ -46,6 +48,7 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.whenever
import org.springframework.context.ApplicationEventPublisher
+import tools.jackson.databind.json.JsonMapper
import java.time.Instant
import java.util.*
@@ -60,6 +63,7 @@ class RequestProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var consentProcessor: ConsentProcessor
private lateinit var requestProcessor: RequestProcessor
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(
@@ -77,8 +81,7 @@ class RequestProcessorTest {
this.applicationEventPublisher = applicationEventPublisher
this.appConfigProperties = AppConfigProperties()
this.consentProcessor = consentProcessor
-
- val objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
requestProcessor =
RequestProcessor(
@@ -86,7 +89,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- objectMapper,
+ jsonMapper,
applicationEventPublisher,
appConfigProperties,
consentProcessor,
@@ -101,7 +104,7 @@ class RequestProcessorTest {
randomRequestId(),
PatientPseudonym("TEST_12345678901"),
PatientId("P1"),
- Fingerprint("6vkiti5bk6ikwifpajpt7cygmd3dvw54d6lwfhzlynb3pqtzferq"),
+ Fingerprint("syehahte4oyqd5m2rbd5imnth4rx6md32g2msb7sztnayxoc4kaq"),
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
@@ -158,7 +161,7 @@ class RequestProcessorTest {
randomRequestId(),
PatientPseudonym("TEST_12345678901"),
PatientId("P1"),
- Fingerprint("4gcjwtjjtcczybsljxepdfpkaeusvd7g3vogfqpmphyffyzfx7dq"),
+ Fingerprint("me6ockoru4boi4ypghfia5myfqtuffwlbszwhtop2rtltb3ycjva"),
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
@@ -413,7 +416,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -637,7 +640,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -681,6 +684,7 @@ class RequestProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var consentProcessor: ConsentProcessor
private lateinit var requestProcessor: RequestProcessor
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(
@@ -698,8 +702,7 @@ class RequestProcessorTest {
this.applicationEventPublisher = applicationEventPublisher
this.appConfigProperties = AppConfigProperties()
this.consentProcessor = consentProcessor
-
- val objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
requestProcessor =
RequestProcessor(
@@ -707,7 +710,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- objectMapper,
+ jsonMapper,
applicationEventPublisher,
appConfigProperties,
consentProcessor,
@@ -779,7 +782,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -883,7 +886,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -994,7 +997,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -1092,7 +1095,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
index 9b103ba..54b4dce 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
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 3b09cc7..441f3a9 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
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 3af5097..66e45f8 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
@@ -24,11 +25,11 @@ 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 java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
+import java.time.Instant
+import java.util.*
class TransformationServiceTest {
@@ -38,7 +39,7 @@ class TransformationServiceTest {
fun setup() {
this.service =
TransformationService(
- JacksonConfig().objectMapper(),
+ JacksonConfig().jsonMapper(),
listOf(
Transformation.of("diagnoses[*].code.version") from "2013" to "2014",
),
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
index 8d5024a..96c9a82 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-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
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.services.kafka
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.services.ResponseEvent
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.junit.jupiter.api.BeforeEach
@@ -36,11 +35,13 @@ import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.springframework.context.ApplicationEventPublisher
import org.springframework.http.HttpStatus
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.module.kotlin.KotlinModule
@ExtendWith(MockitoExtension::class)
class KafkaResponseProcessorTest {
private lateinit var eventPublisher: ApplicationEventPublisher
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var kafkaResponseProcessor: KafkaResponseProcessor
@@ -57,7 +58,7 @@ class KafkaResponseProcessorTest {
if (statusBody == null) {
""
} else {
- this.objectMapper.writeValueAsString(
+ this.jsonMapper.writeValueAsString(
KafkaResponseProcessor.ResponseBody(requestId, statusCode, statusBody),
)
},
@@ -68,9 +69,9 @@ class KafkaResponseProcessorTest {
@Mock eventPublisher: ApplicationEventPublisher,
) {
this.eventPublisher = eventPublisher
- this.objectMapper = ObjectMapper().registerModule(KotlinModule.Builder().build())
+ this.jsonMapper = JsonMapper.builder().addModule(KotlinModule.Builder().build()).build()
- this.kafkaResponseProcessor = KafkaResponseProcessor(eventPublisher, objectMapper)
+ this.kafkaResponseProcessor = KafkaResponseProcessor(eventPublisher, jsonMapper)
}
@Test