mirror of
https://github.com/pcvolkmer/mv64e-etl-processor
synced 2025-09-14 01:12:51 +00:00
feat: support multiple request content types (#109)
This commit is contained in:
@@ -74,7 +74,7 @@ class KafkaInputListenerTest {
|
||||
)
|
||||
)
|
||||
|
||||
verify(requestProcessor, times(1)).processMtbFile(any())
|
||||
verify(requestProcessor, times(1)).processMtbFile(any<MtbFile>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,7 +121,7 @@ class KafkaInputListenerTest {
|
||||
)
|
||||
)
|
||||
|
||||
verify(requestProcessor, times(1)).processMtbFile(any(), anyValueClass())
|
||||
verify(requestProcessor, times(1)).processMtbFile(any<MtbFile>(), anyValueClass())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import de.ukw.ccc.bwhc.dto.*
|
||||
import dev.dnpm.etl.processor.CustomMediaType
|
||||
import dev.dnpm.etl.processor.services.RequestProcessor
|
||||
import dev.pcvolkmer.mv64e.mtb.Mtb
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -72,7 +73,7 @@ class MtbFileRestControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
verify(requestProcessor, times(1)).processMtbFile(any())
|
||||
verify(requestProcessor, times(1)).processMtbFile(any<MtbFile>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -128,7 +129,7 @@ class MtbFileRestControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
verify(requestProcessor, times(1)).processMtbFile(any())
|
||||
verify(requestProcessor, times(1)).processMtbFile(any<MtbFile>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,11 +183,11 @@ class MtbFileRestControllerTest {
|
||||
contentType = CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON
|
||||
}.andExpect {
|
||||
status {
|
||||
isNotImplemented()
|
||||
isAccepted()
|
||||
}
|
||||
}
|
||||
|
||||
verify(requestProcessor, times(0)).processMtbFile(any())
|
||||
verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of ETL-Processor
|
||||
*
|
||||
* Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
|
||||
* Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, 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
|
||||
@@ -21,20 +21,25 @@ package dev.dnpm.etl.processor.output
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import de.ukw.ccc.bwhc.dto.*
|
||||
import de.ukw.ccc.bwhc.dto.Patient
|
||||
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 org.apache.kafka.clients.producer.ProducerRecord
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
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.MethodSource
|
||||
import org.mockito.ArgumentMatchers.anyString
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.jupiter.MockitoExtension
|
||||
import org.mockito.kotlin.*
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.kafka.core.KafkaTemplate
|
||||
import org.springframework.kafka.support.SendResult
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy
|
||||
@@ -45,142 +50,231 @@ import java.util.concurrent.ExecutionException
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class KafkaMtbFileSenderTest {
|
||||
|
||||
private lateinit var kafkaTemplate: KafkaTemplate<String, String>
|
||||
@Nested
|
||||
inner class BwhcV1Record {
|
||||
|
||||
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
|
||||
private lateinit var kafkaTemplate: KafkaTemplate<String, String>
|
||||
|
||||
private lateinit var objectMapper: ObjectMapper
|
||||
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
|
||||
|
||||
@BeforeEach
|
||||
fun setup(
|
||||
@Mock kafkaTemplate: KafkaTemplate<String, String>
|
||||
) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
|
||||
private lateinit var objectMapper: ObjectMapper
|
||||
|
||||
this.objectMapper = ObjectMapper()
|
||||
this.kafkaTemplate = kafkaTemplate
|
||||
@BeforeEach
|
||||
fun setup(
|
||||
@Mock kafkaTemplate: KafkaTemplate<String, String>
|
||||
) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
|
||||
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
|
||||
}
|
||||
this.objectMapper = ObjectMapper()
|
||||
this.kafkaTemplate = kafkaTemplate
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestWithResponseSource")
|
||||
fun shouldSendMtbFileRequestAndReturnExpectedState(testData: TestData) {
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
val response = kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
|
||||
assertThat(response.status).isEqualTo(testData.requestStatus)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestWithResponseSource")
|
||||
fun shouldSendDeleteRequestAndReturnExpectedState(testData: TestData) {
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
val response = kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
assertThat(response.status).isEqualTo(testData.requestStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSendMtbFileRequestWithCorrectKeyAndBody() {
|
||||
doAnswer {
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
|
||||
|
||||
val captor = argumentCaptor<String>()
|
||||
verify(kafkaTemplate, times(1)).send(anyString(), captor.capture(), captor.capture())
|
||||
assertThat(captor.firstValue).isNotNull
|
||||
assertThat(captor.firstValue).isEqualTo("{\"pid\": \"PID\"}")
|
||||
assertThat(captor.secondValue).isNotNull
|
||||
assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData(TEST_REQUEST_ID, Consent.Status.ACTIVE)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSendDeleteRequestWithCorrectKeyAndBody() {
|
||||
doAnswer {
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
|
||||
val captor = argumentCaptor<String>()
|
||||
verify(kafkaTemplate, times(1)).send(anyString(), captor.capture(), captor.capture())
|
||||
assertThat(captor.firstValue).isNotNull
|
||||
assertThat(captor.firstValue).isEqualTo("{\"pid\": \"PID\"}")
|
||||
assertThat(captor.secondValue).isNotNull
|
||||
assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData(TEST_REQUEST_ID, Consent.Status.REJECTED)))
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestWithResponseSource")
|
||||
fun shouldRetryOnMtbFileKafkaSendError(testData: TestData) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
|
||||
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
|
||||
|
||||
val expectedCount = when (testData.exception) {
|
||||
// OK - No Retry
|
||||
null -> times(1)
|
||||
// Request failed - Retry max 3 times
|
||||
else -> times(3)
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
|
||||
}
|
||||
|
||||
verify(kafkaTemplate, expectedCount).send(anyString(), anyString(), anyString())
|
||||
}
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldSendMtbFileRequestAndReturnExpectedState(testData: TestData) {
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestWithResponseSource")
|
||||
fun shouldRetryOnDeleteKafkaSendError(testData: TestData) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
|
||||
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
|
||||
|
||||
kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
|
||||
val expectedCount = when (testData.exception) {
|
||||
// OK - No Retry
|
||||
null -> times(1)
|
||||
// Request failed - Retry max 3 times
|
||||
else -> times(3)
|
||||
val response = kafkaMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, bwhcV1MtbFile(Consent.Status.ACTIVE)))
|
||||
assertThat(response.status).isEqualTo(testData.requestStatus)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldSendDeleteRequestAndReturnExpectedState(testData: TestData) {
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
val response = kafkaMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
assertThat(response.status).isEqualTo(testData.requestStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSendMtbFileRequestWithCorrectKeyAndHeaderAndBody() {
|
||||
doAnswer {
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, bwhcV1MtbFile(Consent.Status.ACTIVE)))
|
||||
|
||||
val captor = argumentCaptor<ProducerRecord<String, String>>()
|
||||
verify(kafkaTemplate, times(1)).send(captor.capture())
|
||||
assertThat(captor.firstValue.key()).isNotNull
|
||||
assertThat(captor.firstValue.key()).isEqualTo("{\"pid\": \"PID\"}")
|
||||
assertThat(captor.firstValue.headers().headers("contentType")).isNotNull
|
||||
assertThat(captor.firstValue.headers().headers("contentType")?.firstOrNull()?.value()).isEqualTo(MediaType.APPLICATION_JSON_VALUE.toByteArray())
|
||||
assertThat(captor.firstValue.value()).isNotNull
|
||||
assertThat(captor.firstValue.value()).isEqualTo(objectMapper.writeValueAsString(bwhcV1kafkaRecordData(TEST_REQUEST_ID, Consent.Status.ACTIVE)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSendDeleteRequestWithCorrectKeyAndBody() {
|
||||
doAnswer {
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
|
||||
val captor = argumentCaptor<ProducerRecord<String, String>>()
|
||||
verify(kafkaTemplate, times(1)).send(captor.capture())
|
||||
assertThat(captor.firstValue.key()).isNotNull
|
||||
assertThat(captor.firstValue.key()).isEqualTo("{\"pid\": \"PID\"}")
|
||||
assertThat(captor.firstValue.value()).isNotNull
|
||||
assertThat(captor.firstValue.value()).isEqualTo(objectMapper.writeValueAsString(bwhcV1kafkaRecordData(TEST_REQUEST_ID, Consent.Status.REJECTED)))
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldRetryOnMtbFileKafkaSendError(testData: TestData) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
|
||||
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, bwhcV1MtbFile(Consent.Status.ACTIVE)))
|
||||
|
||||
val expectedCount = when (testData.exception) {
|
||||
// OK - No Retry
|
||||
null -> times(1)
|
||||
// Request failed - Retry max 3 times
|
||||
else -> times(3)
|
||||
}
|
||||
|
||||
verify(kafkaTemplate, expectedCount).send(any<ProducerRecord<String, String>>())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldRetryOnDeleteKafkaSendError(testData: TestData) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
|
||||
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
|
||||
val expectedCount = when (testData.exception) {
|
||||
// OK - No Retry
|
||||
null -> times(1)
|
||||
// Request failed - Retry max 3 times
|
||||
else -> times(3)
|
||||
}
|
||||
|
||||
verify(kafkaTemplate, expectedCount).send(any<ProducerRecord<String, String>>())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DnpmV2Record {
|
||||
|
||||
private lateinit var kafkaTemplate: KafkaTemplate<String, String>
|
||||
|
||||
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
|
||||
|
||||
private lateinit var objectMapper: ObjectMapper
|
||||
|
||||
@BeforeEach
|
||||
fun setup(
|
||||
@Mock kafkaTemplate: KafkaTemplate<String, String>
|
||||
) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
|
||||
|
||||
this.objectMapper = ObjectMapper()
|
||||
this.kafkaTemplate = kafkaTemplate
|
||||
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldSendMtbFileRequestAndReturnExpectedState(testData: TestData) {
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
val response = kafkaMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
|
||||
assertThat(response.status).isEqualTo(testData.requestStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSendMtbFileRequestWithCorrectKeyAndHeaderAndBody() {
|
||||
doAnswer {
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
|
||||
|
||||
val captor = argumentCaptor<ProducerRecord<String, String>>()
|
||||
verify(kafkaTemplate, times(1)).send(captor.capture())
|
||||
assertThat(captor.firstValue.key()).isNotNull
|
||||
assertThat(captor.firstValue.key()).isEqualTo("{\"pid\": \"PID\"}")
|
||||
assertThat(captor.firstValue.headers().headers("contentType")).isNotNull
|
||||
assertThat(captor.firstValue.headers().headers("contentType")?.firstOrNull()?.value()).isEqualTo(CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE.toByteArray())
|
||||
assertThat(captor.firstValue.value()).isNotNull
|
||||
assertThat(captor.firstValue.value()).isEqualTo(objectMapper.writeValueAsString(dnmpV2kafkaRecordData(TEST_REQUEST_ID)))
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.KafkaMtbFileSenderTest#requestWithResponseSource")
|
||||
fun shouldRetryOnMtbFileKafkaSendError(testData: TestData) {
|
||||
val kafkaProperties = KafkaProperties("testtopic")
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
|
||||
this.kafkaMtbFileSender = KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
|
||||
|
||||
doAnswer {
|
||||
if (null != testData.exception) {
|
||||
throw testData.exception
|
||||
}
|
||||
completedFuture(SendResult<String, String>(null, null))
|
||||
}.whenever(kafkaTemplate).send(any<ProducerRecord<String, String>>())
|
||||
|
||||
kafkaMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
|
||||
|
||||
val expectedCount = when (testData.exception) {
|
||||
// OK - No Retry
|
||||
null -> times(1)
|
||||
// Request failed - Retry max 3 times
|
||||
else -> times(3)
|
||||
}
|
||||
|
||||
verify(kafkaTemplate, expectedCount).send(any<ProducerRecord<String, String>>())
|
||||
}
|
||||
|
||||
verify(kafkaTemplate, expectedCount).send(anyString(), anyString(), anyString())
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TEST_REQUEST_ID = RequestId("TestId")
|
||||
val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
|
||||
|
||||
fun mtbFile(consentStatus: Consent.Status): MtbFile {
|
||||
fun bwhcV1MtbFile(consentStatus: Consent.Status): MtbFile {
|
||||
return if (consentStatus == Consent.Status.ACTIVE) {
|
||||
MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -215,8 +309,31 @@ class KafkaMtbFileSenderTest {
|
||||
}.build()
|
||||
}
|
||||
|
||||
fun kafkaRecordData(requestId: RequestId, consentStatus: Consent.Status): KafkaMtbFileSender.Data {
|
||||
return KafkaMtbFileSender.Data(requestId, mtbFile(consentStatus))
|
||||
fun dnpmV2MtbFile(): Mtb = Mtb.builder()
|
||||
.withPatient(
|
||||
dev.pcvolkmer.mv64e.mtb.Patient.builder()
|
||||
.withId("PID")
|
||||
.withBirthDate("2000-08-08")
|
||||
.withGender(CodingGender.builder().withCode(CodingGender.Code.MALE).build())
|
||||
.build()
|
||||
)
|
||||
.withEpisodesOfCare(
|
||||
listOf(
|
||||
MTBEpisodeOfCare.builder()
|
||||
.withId("1")
|
||||
.withPatient(Reference("PID"))
|
||||
.withPeriod(PeriodDate.builder().withStart("2023-08-08").build())
|
||||
.build()
|
||||
)
|
||||
)
|
||||
.build()
|
||||
|
||||
fun bwhcV1kafkaRecordData(requestId: RequestId, consentStatus: Consent.Status): MtbRequest {
|
||||
return BwhcV1MtbFileRequest(requestId, bwhcV1MtbFile(consentStatus))
|
||||
}
|
||||
|
||||
fun dnmpV2kafkaRecordData(requestId: RequestId): MtbRequest {
|
||||
return DnpmV2MtbFileRequest(requestId, dnpmV2MtbFile())
|
||||
}
|
||||
|
||||
data class TestData(val requestStatus: RequestStatus, val exception: Throwable? = null)
|
||||
@@ -231,4 +348,4 @@ class KafkaMtbFileSenderTest {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -30,16 +30,16 @@ import dev.dnpm.etl.processor.monitoring.RequestStatus
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy
|
||||
import org.springframework.retry.support.RetryTemplateBuilder
|
||||
import org.springframework.test.web.client.ExpectedCount
|
||||
import org.springframework.test.web.client.MockRestServiceServer
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.method
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
|
||||
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
@@ -73,7 +73,7 @@ class RestBwhcMtbFileSenderTest {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
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)
|
||||
}
|
||||
@@ -84,11 +84,12 @@ class RestBwhcMtbFileSenderTest {
|
||||
this.mockRestServiceServer
|
||||
.expect(method(HttpMethod.POST))
|
||||
.andExpect(requestTo("http://localhost:9000/mtbfile/MTBFile"))
|
||||
.andExpect(header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
|
||||
.andRespond {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
val response = restMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
@@ -118,7 +119,7 @@ class RestBwhcMtbFileSenderTest {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
val response = restMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
@@ -148,7 +149,7 @@ class RestBwhcMtbFileSenderTest {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
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)
|
||||
}
|
||||
@@ -309,4 +310,4 @@ class RestBwhcMtbFileSenderTest {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,8 @@ package dev.dnpm.etl.processor.output
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import de.ukw.ccc.bwhc.dto.*
|
||||
import de.ukw.ccc.bwhc.dto.Patient
|
||||
import dev.dnpm.etl.processor.CustomMediaType
|
||||
import dev.dnpm.etl.processor.PatientPseudonym
|
||||
import dev.dnpm.etl.processor.RequestId
|
||||
import dev.dnpm.etl.processor.config.AppConfigProperties
|
||||
@@ -29,136 +31,206 @@ 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.dnpm.etl.processor.output.RestBwhcMtbFileSenderTest.Companion
|
||||
import dev.pcvolkmer.mv64e.mtb.*
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.retry.backoff.NoBackOffPolicy
|
||||
import org.springframework.retry.policy.SimpleRetryPolicy
|
||||
import org.springframework.retry.support.RetryTemplateBuilder
|
||||
import org.springframework.test.web.client.ExpectedCount
|
||||
import org.springframework.test.web.client.MockRestServiceServer
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.method
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
|
||||
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
|
||||
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
class RestDipMtbFileSenderTest {
|
||||
|
||||
private lateinit var mockRestServiceServer: MockRestServiceServer
|
||||
@Nested
|
||||
inner class BwhcV1ContentRequest {
|
||||
|
||||
private lateinit var restMtbFileSender: RestMtbFileSender
|
||||
private lateinit var mockRestServiceServer: MockRestServiceServer
|
||||
|
||||
private var reportService = ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
|
||||
private lateinit var restMtbFileSender: RestMtbFileSender
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
val restTemplate = RestTemplate()
|
||||
val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
|
||||
private var reportService = ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
|
||||
|
||||
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
val restTemplate = RestTemplate()
|
||||
val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
|
||||
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
|
||||
|
||||
this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
|
||||
}
|
||||
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mtbFileRequestWithResponseSource")
|
||||
fun shouldReturnExpectedResponseForMtbFilePost(requestWithResponse: RequestWithResponse) {
|
||||
this.mockRestServiceServer
|
||||
.expect(method(HttpMethod.POST))
|
||||
.andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
|
||||
.andRespond {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mtbFileRequestWithResponseSource")
|
||||
fun shouldRetryOnMtbFileHttpRequestError(requestWithResponse: RequestWithResponse) {
|
||||
val restTemplate = RestTemplate()
|
||||
val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
|
||||
val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000"))
|
||||
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.POST))
|
||||
.andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
|
||||
.andRespond {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
@ParameterizedTest
|
||||
@MethodSource("dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#mtbFileRequestWithResponseSource")
|
||||
fun shouldReturnExpectedResponseForMtbFilePost(requestWithResponse: RequestWithResponse) {
|
||||
this.mockRestServiceServer
|
||||
.expect(method(HttpMethod.POST))
|
||||
.andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
|
||||
.andExpect(header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
|
||||
.andRespond {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("deleteRequestWithResponseSource")
|
||||
fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
|
||||
val restTemplate = RestTemplate()
|
||||
val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
|
||||
val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000"))
|
||||
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)
|
||||
val response = restMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, bwhcV1mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
|
||||
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#mtbFileRequestWithResponseSource")
|
||||
fun shouldRetryOnMtbFileHttpRequestError(requestWithResponse: RequestWithResponse) {
|
||||
val restTemplate = RestTemplate()
|
||||
val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
|
||||
val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000"))
|
||||
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)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
this.mockRestServiceServer
|
||||
.expect(expectedCount, method(HttpMethod.POST))
|
||||
.andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
|
||||
.andRespond {
|
||||
withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
|
||||
}
|
||||
|
||||
val response = restMtbFileSender.send(BwhcV1MtbFileRequest(TEST_REQUEST_ID, bwhcV1mtbFile))
|
||||
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
|
||||
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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, false)
|
||||
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)
|
||||
}
|
||||
|
||||
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, false)
|
||||
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)
|
||||
}
|
||||
|
||||
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, false)
|
||||
val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000"))
|
||||
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 {
|
||||
@@ -171,7 +243,7 @@ class RestDipMtbFileSenderTest {
|
||||
val TEST_REQUEST_ID = RequestId("TestId")
|
||||
val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
|
||||
|
||||
val mtbFile: MtbFile = MtbFile.builder()
|
||||
val bwhcV1mtbFile: MtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
Patient.builder()
|
||||
.withId("PID")
|
||||
@@ -195,6 +267,25 @@ class RestDipMtbFileSenderTest {
|
||||
)
|
||||
.build()
|
||||
|
||||
val dnpmV2MtbFile: Mtb = Mtb.builder()
|
||||
.withPatient(
|
||||
dev.pcvolkmer.mv64e.mtb.Patient.builder()
|
||||
.withId("PID")
|
||||
.withBirthDate("2000-08-08")
|
||||
.withGender(CodingGender.builder().withCode(CodingGender.Code.MALE).build())
|
||||
.build()
|
||||
)
|
||||
.withEpisodesOfCare(
|
||||
listOf(
|
||||
MTBEpisodeOfCare.builder()
|
||||
.withId("1")
|
||||
.withPatient(Reference("PID"))
|
||||
.withPeriod(PeriodDate.builder().withStart("2023-08-08").build())
|
||||
.build()
|
||||
)
|
||||
)
|
||||
.build()
|
||||
|
||||
private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
|
||||
|
||||
/**
|
||||
@@ -311,4 +402,4 @@ class RestDipMtbFileSenderTest {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -21,14 +21,19 @@ package dev.dnpm.etl.processor.services
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import de.ukw.ccc.bwhc.dto.*
|
||||
import dev.dnpm.etl.processor.*
|
||||
import dev.dnpm.etl.processor.Fingerprint
|
||||
import dev.dnpm.etl.processor.PatientId
|
||||
import dev.dnpm.etl.processor.PatientPseudonym
|
||||
import dev.dnpm.etl.processor.config.AppConfigProperties
|
||||
import dev.dnpm.etl.processor.monitoring.Request
|
||||
import dev.dnpm.etl.processor.monitoring.RequestStatus
|
||||
import dev.dnpm.etl.processor.monitoring.RequestType
|
||||
import dev.dnpm.etl.processor.output.BwhcV1MtbFileRequest
|
||||
import dev.dnpm.etl.processor.output.DeleteRequest
|
||||
import dev.dnpm.etl.processor.output.MtbFileSender
|
||||
import dev.dnpm.etl.processor.output.RestMtbFileSender
|
||||
import dev.dnpm.etl.processor.pseudonym.PseudonymizeService
|
||||
import dev.dnpm.etl.processor.randomRequestId
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -109,7 +114,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0]
|
||||
}.whenever(transformationService).transform(any())
|
||||
}.whenever(transformationService).transform(any<MtbFile>())
|
||||
|
||||
val mtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -168,7 +173,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0]
|
||||
}.whenever(transformationService).transform(any())
|
||||
}.whenever(transformationService).transform(any<MtbFile>())
|
||||
|
||||
val mtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -223,7 +228,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.SUCCESS)
|
||||
}.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
|
||||
}.whenever(sender).send(any<BwhcV1MtbFileRequest>())
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0] as String
|
||||
@@ -231,7 +236,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0]
|
||||
}.whenever(transformationService).transform(any())
|
||||
}.whenever(transformationService).transform(any<MtbFile>())
|
||||
|
||||
val mtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -286,7 +291,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.ERROR)
|
||||
}.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
|
||||
}.whenever(sender).send(any<BwhcV1MtbFileRequest>())
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0] as String
|
||||
@@ -294,7 +299,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0]
|
||||
}.whenever(transformationService).transform(any())
|
||||
}.whenever(transformationService).transform(any<MtbFile>())
|
||||
|
||||
val mtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -336,7 +341,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.UNKNOWN)
|
||||
}.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
|
||||
}.whenever(sender).send(any<DeleteRequest>())
|
||||
|
||||
this.requestProcessor.processDeletion(TEST_PATIENT_ID)
|
||||
|
||||
@@ -354,7 +359,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.SUCCESS)
|
||||
}.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
|
||||
}.whenever(sender).send(any<DeleteRequest>())
|
||||
|
||||
this.requestProcessor.processDeletion(TEST_PATIENT_ID)
|
||||
|
||||
@@ -372,7 +377,7 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.ERROR)
|
||||
}.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
|
||||
}.whenever(sender).send(any<DeleteRequest>())
|
||||
|
||||
this.requestProcessor.processDeletion(TEST_PATIENT_ID)
|
||||
|
||||
@@ -404,11 +409,11 @@ class RequestProcessorTest {
|
||||
|
||||
doAnswer {
|
||||
it.arguments[0]
|
||||
}.whenever(transformationService).transform(any())
|
||||
}.whenever(transformationService).transform(any<MtbFile>())
|
||||
|
||||
doAnswer {
|
||||
MtbFileSender.Response(status = RequestStatus.SUCCESS)
|
||||
}.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
|
||||
}.whenever(sender).send(any<BwhcV1MtbFileRequest>())
|
||||
|
||||
val mtbFile = MtbFile.builder()
|
||||
.withPatient(
|
||||
@@ -446,4 +451,4 @@ class RequestProcessorTest {
|
||||
val TEST_PATIENT_ID = PatientId("TEST_12345678901")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user