diff options
Diffstat (limited to 'src/test/java/dev/dnpm')
30 files changed, 3198 insertions, 0 deletions
diff --git a/src/test/java/dev/dnpm/ConsentManagerTest.java b/src/test/java/dev/dnpm/ConsentManagerTest.java new file mode 100644 index 0000000..96d21e5 --- /dev/null +++ b/src/test/java/dev/dnpm/ConsentManagerTest.java @@ -0,0 +1,63 @@ +package dev.dnpm; + +import dev.dnpm.analyzer.ConsentManager; +import dev.dnpm.services.consent.ConsentManagerServiceFactory; +import dev.dnpm.services.consent.MrConsentManagerService; +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ConsentManagerTest { + + private IOnkostarApi onkostarApi; + + private ConsentManagerServiceFactory consentManagerServiceFactory; + + private ConsentManager consentManager; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock ConsentManagerServiceFactory consentManagerServiceFactory + ) { + this.onkostarApi = onkostarApi; + this.consentManagerServiceFactory = consentManagerServiceFactory; + this.consentManager = new ConsentManager(onkostarApi, consentManagerServiceFactory); + } + + @Test + void shouldRunServiceMethodsOnAnalyzeCalled() { + var consentManagerServiceMock = mock(MrConsentManagerService.class); + + when(consentManagerServiceMock.canApply(any(Procedure.class))).thenReturn(true); + + when(this.consentManagerServiceFactory.currentUsableInstance()) + .thenReturn(consentManagerServiceMock); + + this.consentManager.analyze(new Procedure(onkostarApi), null); + + verify(consentManagerServiceMock, times(1)).applyConsent(any(Procedure.class)); + } + + @Test + void shouldNotRunServiceMethodsIfProcedureCannotBeAppliesForForm() { + var consentManagerServiceMock = mock(MrConsentManagerService.class); + + when(consentManagerServiceMock.canApply(any(Procedure.class))).thenReturn(false); + + when(this.consentManagerServiceFactory.currentUsableInstance()) + .thenReturn(consentManagerServiceMock); + + this.consentManager.analyze(new Procedure(onkostarApi), null); + + verify(consentManagerServiceMock, times(0)).applyConsent(any(Procedure.class)); + } + +} diff --git a/src/test/java/dev/dnpm/DNPMHelperTest.java b/src/test/java/dev/dnpm/DNPMHelperTest.java new file mode 100644 index 0000000..9aa08dd --- /dev/null +++ b/src/test/java/dev/dnpm/DNPMHelperTest.java @@ -0,0 +1,295 @@ +package dev.dnpm; + +import dev.dnpm.analyzer.DNPMHelper; +import dev.dnpm.security.DelegatingDataBasedPermissionEvaluator; +import dev.dnpm.security.IllegalSecuredObjectAccessException; +import dev.dnpm.security.PermissionType; +import dev.dnpm.services.systemtherapie.SystemtherapieService; +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class DNPMHelperTest { + + private IOnkostarApi onkostarApi; + + private SystemtherapieService systemtherapieService; + + private DelegatingDataBasedPermissionEvaluator delegatingDataBasedPermissionEvaluator; + + private DNPMHelper dnpmHelper; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock SystemtherapieService systemtherapieService, + @Mock DelegatingDataBasedPermissionEvaluator delegatingDataBasedPermissionEvaluator + ) { + this.onkostarApi = onkostarApi; + this.systemtherapieService = systemtherapieService; + this.delegatingDataBasedPermissionEvaluator = delegatingDataBasedPermissionEvaluator; + this.dnpmHelper = new DNPMHelper(onkostarApi, systemtherapieService, delegatingDataBasedPermissionEvaluator); + } + + @Test + void testShouldRequestSystemischeTherapienFromDiagnose() { + dnpmHelper.getSystemischeTherapienFromDiagnose(Map.of("DiagnoseId", 1234)); + + var captor = ArgumentCaptor.forClass(Integer.class); + verify(systemtherapieService, times(1)).getSystemischeTherapienFromDiagnose(captor.capture()); + assertThat(captor.getValue()).isEqualTo(1234); + } + + @Test + void testShouldReturnNullIfNoDiagnoseIdCallingGetSystemischeTherapienFromDiagnose() { + var actual = dnpmHelper.getSystemischeTherapienFromDiagnose(new HashMap<>()); + + assertThat(actual).isNull(); + } + + @Test + void testShouldReturnNullIfNoProcedureIdCallingGetEmpfehlung() { + var actual = dnpmHelper.getEmpfehlung(new HashMap<>()); + + assertThat(actual).isNull(); + } + + @Nested + class UpdateEmpfehlungPrioTests { + + @Test + void testShouldReturnFalseIfNoRidAndNoBdCallingUpdateEmpfehlungPrio() { + var actual = dnpmHelper.updateEmpfehlungPrio(new HashMap<>()); + + assertThat(actual).isEqualTo(false); + } + + @Test + void testShouldReturnFalseIfNoRidCallingUpdateEmpfehlungPrio() { + var actual = dnpmHelper.updateEmpfehlungPrio(Map.of("bd", "2023-01-01")); + + assertThat(actual).isEqualTo(false); + } + + @Test + void testShouldReturnFalseIfNoBdCallingUpdateEmpfehlungPrio() { + var actual = dnpmHelper.updateEmpfehlungPrio(Map.of("rid", 1234)); + + assertThat(actual).isEqualTo(false); + } + + @Test + void testShouldReturnTrueIfRidAndBdPresentCallingUpdateEmpfehlungPrio() { + var sessionFactory = mock(SessionFactory.class); + var session = mock(Session.class); + var query = mock(SQLQuery.class); + + when(onkostarApi.getSessionFactory()).thenReturn(sessionFactory); + when(sessionFactory.getCurrentSession()).thenReturn(session); + when(session.createSQLQuery(anyString())).thenReturn(query); + + var actual = dnpmHelper.updateEmpfehlungPrio(Map.of("rid", 1234, "bd", "2023-01-01")); + + assertThat(actual).isEqualTo(true); + } + + @Test + void testShouldCreateSqlQueryWithRidAndBdCallingUpdateEmpfehlungPrio() { + var sessionFactory = mock(SessionFactory.class); + var session = mock(Session.class); + var query = mock(SQLQuery.class); + + when(onkostarApi.getSessionFactory()).thenReturn(sessionFactory); + when(sessionFactory.getCurrentSession()).thenReturn(session); + when(session.createSQLQuery(anyString())).thenReturn(query); + + dnpmHelper.updateEmpfehlungPrio(Map.of("rid", 1234, "bd", "2023-01-01")); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(session, times(1)).createSQLQuery(argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).isEqualTo("UPDATE prozedur SET beginndatum = '2023-01-01' WHERE id = '1234' "); + } + + } + + @Nested + class GetProzedurenFromDiagnoseTests { + @Test + void testShouldReturnEmptyStringOnParamCheckIfNoDataFormParamGiven() { + var actual = dnpmHelper.getProzedurenFromDiagnose(Map.of("DiagnoseId", 1, "PatientId", 2)); + assertThat(actual).isExactlyInstanceOf(String.class).isEmpty(); + + verify(onkostarApi, times(0)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldReturnEmptyStringOnParamCheckIfNoDiagnoseIdParamGiven() { + var actual = dnpmHelper.getProzedurenFromDiagnose(Map.of("dataForm", "OS.Example", "PatientId", 2)); + assertThat(actual).isExactlyInstanceOf(String.class).isEmpty(); + + verify(onkostarApi, times(0)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldReturnEmptyStringOnParamCheckIfNoPatientIdParamGiven() { + var actual = dnpmHelper.getProzedurenFromDiagnose(Map.of("dataForm", "OS.Example", "DiagnoseId", 1)); + assertThat(actual).isExactlyInstanceOf(String.class).isEmpty(); + + verify(onkostarApi, times(0)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldRequestProceduresIfRequiredParamsGiven() { + dnpmHelper.getProzedurenFromDiagnose(Map.of("dataForm", "OS.Example", "DiagnoseId", 1, "PatientId", 2)); + verify(onkostarApi, times(1)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldNotReturnProceduresNotRelatedToDisease() { + doAnswer(invocationOnMock -> { + var procedure = new Procedure(onkostarApi); + procedure.setFormName("OS.Example1"); + procedure.setId(11); + procedure.addDiseaseId(4711); + procedure.setValue("formfield", new Item("formfield", "Wert11")); + + return List.of(procedure); + }).when(onkostarApi).getProceduresByPatientId(anyInt()); + + var actual = dnpmHelper.getProzedurenFromDiagnose(Map.of("dataForm", "OS.Example", "DiagnoseId", 1, "PatientId", 2)); + assertThat(actual).isEqualTo("[]"); + } + + @Test + void testShouldReturnProcedures() { + doAnswer(invocationOnMock -> { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Example1"); + procedure1.setId(11); + procedure1.addDiseaseId(1); + procedure1.setStartDate(new Date()); + procedure1.setValue("formfield", new Item("formfield", "Wert11")); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setFormName("OS.Example2"); + procedure2.setId(21); + procedure2.addDiseaseId(1); + procedure2.setStartDate(new Date()); + procedure2.setValue("formfield", new Item("formfield", "Wert21")); + + var procedure3 = new Procedure(onkostarApi); + procedure3.setFormName("OS.Example1"); + procedure3.setId(12); + procedure3.addDiseaseId(1); + procedure3.setStartDate(new Date()); + procedure3.setValue("formfield", new Item("formfield", "Wert12")); + + return List.of(procedure1, procedure2, procedure3); + }).when(onkostarApi).getProceduresByPatientId(anyInt()); + + var actual = dnpmHelper.getProzedurenFromDiagnose(Map.of("dataForm", "OS.Example", "DiagnoseId", 1, "PatientId", 2)); + assertThat(actual).contains("OS.Example1", "OS.Example2", "Wert11", "Wert21", "Wert12"); + } + } + + @Nested + class GetVerweiseTests { + + @Test + void testShouldReturnEmptyArrayIfNoProcedureIdParamGiven() { + var actual = dnpmHelper.getVerweise(Map.of("PatientId", 2)); + assertThat(actual).isNull(); + + verify(onkostarApi, times(0)).getSessionFactory(); + } + + @Test + void testShouldReturnEmptyArrayIfNoPatientIdParamGiven() { + var actual = dnpmHelper.getVerweise(Map.of("ProcedureId", 1)); + assertThat(actual).isNull(); + + verify(onkostarApi, times(0)).getSessionFactory(); + } + + @Test + void testShouldRequestSessionFactoryIfRequiredParamsGiven() { + dnpmHelper.getVerweise(Map.of("ProcedureId", 1, "PatientId", 2)); + verify(onkostarApi, times(1)).getSessionFactory(); + } + + @Test + void testShouldCreateSqlQueryWithPatientId() { + var sessionFactory = mock(SessionFactory.class); + var session = mock(Session.class); + var query = mock(SQLQuery.class); + + when(onkostarApi.getSessionFactory()).thenReturn(sessionFactory); + when(sessionFactory.getCurrentSession()).thenReturn(session); + when(session.createSQLQuery(anyString())).thenReturn(query); + + dnpmHelper.getVerweise(Map.of("ProcedureId", 1, "PatientId", 2)); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(session, times(1)).createSQLQuery(argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).contains("WHERE patient_id = 2 AND geloescht = 0"); + } + + @Test + void testShouldReturnEcogStatusList() { + when(delegatingDataBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(true); + + doAnswer(invocationOnMock -> { + var id = invocationOnMock.getArgument(0, Integer.class); + var patient = new Patient(onkostarApi); + patient.setId(id); + return patient; + }).when(onkostarApi).getPatient(anyInt()); + + dnpmHelper.getEcogStatus(Map.of("PatientId", 42)); + + var argumentCaptor = ArgumentCaptor.forClass(Patient.class); + verify(systemtherapieService, times(1)).ecogStatus(argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).isNotNull(); + assertThat(argumentCaptor.getValue().getId()).isEqualTo(42); + } + + @Test + void testShouldNotReturnEcogStatusListIfNoPermissionGranted() { + when(delegatingDataBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(false); + + doAnswer(invocationOnMock -> { + var id = invocationOnMock.getArgument(0, Integer.class); + var patient = new Patient(onkostarApi); + patient.setId(id); + return patient; + }).when(onkostarApi).getPatient(anyInt()); + + assertThrows(IllegalSecuredObjectAccessException.class, () -> dnpmHelper.getEcogStatus(Map.of("PatientId", 42))); + } + + } + +} diff --git a/src/test/java/dev/dnpm/MerkmalskatalogTest.java b/src/test/java/dev/dnpm/MerkmalskatalogTest.java new file mode 100644 index 0000000..bd877f0 --- /dev/null +++ b/src/test/java/dev/dnpm/MerkmalskatalogTest.java @@ -0,0 +1,68 @@ +package dev.dnpm; + +import dev.dnpm.analyzer.Merkmalskatalog; +import de.itc.onkostar.api.IOnkostarApi; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class MerkmalskatalogTest { + + private IOnkostarApi onkostarApi; + + private Merkmalskatalog merkmalskatalog; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.merkmalskatalog = new Merkmalskatalog(onkostarApi); + } + + @Test + void testShouldReturnNullOnParamCheckIfNoMerkmalskatalogParamGiven() { + var actual = merkmalskatalog.getMerkmalskatalog(Map.of("Spalten", "id, code")); + assertThat(actual).isNull(); + + verify(onkostarApi, times(0)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldReturnNullOnParamCheckIfNoSpaltenParamGiven() { + var actual = merkmalskatalog.getMerkmalskatalog(Map.of("Merkmalskatalog", "MK1")); + assertThat(actual).isNull(); + + verify(onkostarApi, times(0)).getProceduresByPatientId(anyInt()); + } + + @Test + void testShouldCreateSqlQueryWithMerkmalskatalog() { + var sessionFactory = mock(SessionFactory.class); + var session = mock(Session.class); + var query = mock(SQLQuery.class); + + when(onkostarApi.getSessionFactory()).thenReturn(sessionFactory); + when(sessionFactory.getCurrentSession()).thenReturn(session); + when(session.createSQLQuery(anyString())).thenReturn(query); + + merkmalskatalog.getMerkmalskatalog(Map.of("Merkmalskatalog", "MK1", "Spalten", "id, code")); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(session, times(1)).createSQLQuery(argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).contains("WHERE name = 'MK1' AND aktiv = 1"); + } + +} diff --git a/src/test/java/dev/dnpm/analyzer/AnalyzerUtilsTest.java b/src/test/java/dev/dnpm/analyzer/AnalyzerUtilsTest.java new file mode 100644 index 0000000..2d51bbc --- /dev/null +++ b/src/test/java/dev/dnpm/analyzer/AnalyzerUtilsTest.java @@ -0,0 +1,137 @@ +package dev.dnpm.analyzer; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class AnalyzerUtilsTest { + + private final Map<String, Object> input = Map.of("value1", 1, "valueA", "A", "valueTrue", true); + + private static Set<TestTypeData> testTypeData() { + return Set.of( + new TestTypeData("value1", Integer.class).withExpectedResult(true), + new TestTypeData("valueA", String.class).withExpectedResult(true), + new TestTypeData("valueTrue", Boolean.class).withExpectedResult(true), + + new TestTypeData("value1", String.class).withExpectedResult(false), + new TestTypeData("valueA", Boolean.class).withExpectedResult(false), + new TestTypeData("valueTrue", Integer.class).withExpectedResult(false), + + new TestTypeData("value1", Boolean.class).withExpectedResult(false), + new TestTypeData("valueA", Integer.class).withExpectedResult(false), + new TestTypeData("valueTrue", String.class).withExpectedResult(false) + ); + } + + @ParameterizedTest + @MethodSource("testTypeData") + void testShouldReturnExpectedResultForTypedCheck(TestTypeData testData) { + var actual = AnalyzerUtils.requiredValuePresent(input, testData.key, testData.type); + assertThat(actual).isEqualTo(testData.result); + } + + private static Set<TestMatchData> testMatchData() { + return Set.of( + new TestMatchData("value1", "[\\d]").withExpectedResult(true), + new TestMatchData("valueA", "[A-Z]").withExpectedResult(true), + + new TestMatchData("value1", "[A-Z]").withExpectedResult(false), + new TestMatchData("valueA", "[a-z]").withExpectedResult(false), + new TestMatchData("valueA", "[\\d]").withExpectedResult(false) + ); + } + + @ParameterizedTest + @MethodSource("testMatchData") + void testShouldReturnExpectedResultForMatchCheck(TestMatchData testData) { + var actual = AnalyzerUtils.requiredValueMatches(input, testData.key, testData.regexp); + assertThat(actual).isEqualTo(testData.result); + } + + @Test + void testShouldCheckIfInputValueIsIdNumber() { + assertThat(AnalyzerUtils.requiredValueIsId(Map.of("value", 0), "value")).isFalse(); + assertThat(AnalyzerUtils.requiredValueIsId(Map.of("value", "ABC"), "value")).isFalse(); + assertThat(AnalyzerUtils.requiredValueIsId(Map.of("value", 1234), "value")).isTrue(); + } + + @Test + void testShouldReturnInputValueAsOptional() { + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", 1234), "value", Integer.class)).isEqualTo(Optional.of(1234)); + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", "ABC"), "value", String.class)).isEqualTo(Optional.of("ABC")); + + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", 1234), "value1", Integer.class)).isEmpty(); + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", "ABC"), "value1", String.class)).isEmpty(); + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", 1234), "value", String.class)).isEmpty(); + assertThat(AnalyzerUtils.getRequiredValue(Map.of("value", "ABC"), "value", Boolean.class)).isEmpty(); + } + + @Test + void testShouldReturnInputIdAsOptional() { + assertThat(AnalyzerUtils.getRequiredId(Map.of("value", 1234), "value")).isEqualTo(Optional.of(1234)); + + assertThat(AnalyzerUtils.getRequiredId(Map.of("value", 1234), "value1")).isEmpty(); + assertThat(AnalyzerUtils.getRequiredId(Map.of("value", "ABC"), "value")).isEmpty(); + assertThat(AnalyzerUtils.getRequiredId(Map.of("value", 0), "value")).isEmpty(); + } + + @Test + void testShouldReturnInputValueMatchingAsOptional() { + assertThat(AnalyzerUtils.getRequiredValueMatching(Map.of("value", 1234), "value", "[\\d]+")).isEqualTo(Optional.of("1234")); + assertThat(AnalyzerUtils.getRequiredValueMatching(Map.of("value", "ABC"), "value", "[A-Z]+")).isEqualTo(Optional.of("ABC")); + + assertThat(AnalyzerUtils.getRequiredValueMatching(Map.of("value", "ABC"), "value1", "[A-Z]+")).isEmpty(); + } + + private static class TestTypeData { + public final String key; + public final Class<?> type; + + public boolean result; + + public TestTypeData(String key, Class<?> type) { + this.key = key; + this.type = type; + } + + public TestTypeData withExpectedResult(boolean result) { + this.result = result; + return this; + } + + @Override + public String toString() { + return String.format("key: '%s', type: %s, result: %s", key, type.getSimpleName(), result); + } + } + + private static class TestMatchData { + public final String key; + public final String regexp; + + public boolean result; + + public TestMatchData(String key, String regexp) { + this.key = key; + this.regexp = regexp; + } + + public TestMatchData withExpectedResult(boolean result) { + this.result = result; + return this; + } + + @Override + public String toString() { + return String.format("key: '%s', regexp: '%s', result: %s", key, regexp, result); + } + } + +} diff --git a/src/test/java/dev/dnpm/analyzer/EinzelempfehlungAnalyzerTest.java b/src/test/java/dev/dnpm/analyzer/EinzelempfehlungAnalyzerTest.java new file mode 100644 index 0000000..fbc1d92 --- /dev/null +++ b/src/test/java/dev/dnpm/analyzer/EinzelempfehlungAnalyzerTest.java @@ -0,0 +1,103 @@ +package dev.dnpm.analyzer; + +import dev.dnpm.security.PermissionType; +import dev.dnpm.security.PersonPoolBasedPermissionEvaluator; +import dev.dnpm.services.StudienService; +import dev.dnpm.services.molekulargenetik.MolekulargenetikFormService; +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class EinzelempfehlungAnalyzerTest { + + private IOnkostarApi onkostarApi; + + private StudienService studienService; + + private MolekulargenetikFormService molekulargenetikFormService; + + private PersonPoolBasedPermissionEvaluator permissionEvaluator; + + private EinzelempfehlungAnalyzer analyzer; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock StudienService studienService, + @Mock MolekulargenetikFormService molekulargenetikFormService, + @Mock PersonPoolBasedPermissionEvaluator permissionEvaluator + ) { + this.onkostarApi = onkostarApi; + this.studienService = studienService; + this.molekulargenetikFormService = molekulargenetikFormService; + this.permissionEvaluator = permissionEvaluator; + this.analyzer = new EinzelempfehlungAnalyzer(onkostarApi, studienService, molekulargenetikFormService, permissionEvaluator); + } + + @Test + void testShouldRequestVariantsFromMolekulargenetikFormService() { + doAnswer(invocationOnMock -> new Procedure(this.onkostarApi)).when(onkostarApi).getProcedure(anyInt()); + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(true); + + analyzer.getVariants(Map.of("id", 123)); + verify(molekulargenetikFormService, times(1)).getVariants(any(Procedure.class)); + } + + @Test + void shouldRequestAllStudienForEmptyQueryString() { + var input = Map.of("q", (Object) " "); + this.analyzer.getStudien(input); + + verify(studienService, times(1)).findActive(); + } + + @Test + void shouldRequestActiveStudienForEmptyInputMap() { + var input = new HashMap<String, Object>(); + this.analyzer.getStudien(input); + + verify(studienService, times(1)).findActive(); + } + + @Test + void shouldRequestFilteredActiveStudien() { + var input = Map.of("q", (Object) "NCT-123"); + this.analyzer.getStudien(input); + + var captor = ArgumentCaptor.forClass(String.class); + verify(studienService, times(1)).findActiveByQuery(captor.capture()); + assertThat(captor.getValue()).isEqualTo("NCT-123"); + } + + @Test + void shouldRequestActiveStudien() { + var input = Map.of("q", (Object) ""); + this.analyzer.getStudien(input); + + verify(studienService, times(1)).findActive(); + } + + @Test + void shouldRequestAllFilteredtudien() { + var input = Map.of("q", (Object) "NCT-123"); + this.analyzer.getStudien(input); + + var captor = ArgumentCaptor.forClass(String.class); + verify(studienService, times(1)).findActiveByQuery(captor.capture()); + assertThat(captor.getValue()).isEqualTo("NCT-123"); + } + +} diff --git a/src/test/java/dev/dnpm/analyzer/FollowUpAnalyzerTest.java b/src/test/java/dev/dnpm/analyzer/FollowUpAnalyzerTest.java new file mode 100644 index 0000000..cfe5427 --- /dev/null +++ b/src/test/java/dev/dnpm/analyzer/FollowUpAnalyzerTest.java @@ -0,0 +1,80 @@ +package dev.dnpm.analyzer; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class FollowUpAnalyzerTest { + + private IOnkostarApi onkostarApi; + + private FollowUpAnalyzer followUpAnalyzer; + + @BeforeEach + void setUp( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.followUpAnalyzer = new FollowUpAnalyzer(onkostarApi); + } + + @Test + void shouldBacklinkEinzelempfehlungUsingOnkostarApi() throws Exception { + var einzelempfehlung = new Procedure(onkostarApi); + einzelempfehlung.setId(1234); + + when(onkostarApi.getProcedure(anyInt())).thenReturn(einzelempfehlung); + + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setValue("LinkTherapieempfehlung", new Item("LinkTherapieempfehlung", 1234)); + + followUpAnalyzer.analyze(procedure, null); + + var procedureIdCaptor = ArgumentCaptor.forClass(Integer.class); + verify(onkostarApi, times(1)).getProcedure(procedureIdCaptor.capture()); + assertThat(procedureIdCaptor.getValue()).isEqualTo(einzelempfehlung.getId()); + + var procedureCaptor = ArgumentCaptor.forClass(Procedure.class); + verify(onkostarApi, times(1)).saveProcedure(procedureCaptor.capture()); + assertThat(procedureCaptor.getValue()).isNotNull(); + assertThat(procedureCaptor.getValue().getId()).isEqualTo(einzelempfehlung.getId()); + } + + @Test + void shouldNotBacklinkEinzelempfehlungIfNoEinzelempfehlungSelected() throws Exception { + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + + followUpAnalyzer.analyze(procedure, null); + + verify(onkostarApi, times(0)).getProcedure(anyInt()); + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class)); + } + + @Test + void shouldNotBacklinkEinzelempfehlungIfEinzelempfehlungDoesNotExist() throws Exception { + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setValue("LinkTherapieempfehlung", new Item("LinkTherapieempfehlung", 1234)); + + followUpAnalyzer.analyze(procedure, null); + + var procedureIdCaptor = ArgumentCaptor.forClass(Integer.class); + verify(onkostarApi, times(1)).getProcedure(procedureIdCaptor.capture()); + assertThat(procedureIdCaptor.getValue()).isEqualTo(1234); + + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class)); + } + +} diff --git a/src/test/java/dev/dnpm/analyzer/TherapieMitEcogAnalyzerTest.java b/src/test/java/dev/dnpm/analyzer/TherapieMitEcogAnalyzerTest.java new file mode 100644 index 0000000..a37ac06 --- /dev/null +++ b/src/test/java/dev/dnpm/analyzer/TherapieMitEcogAnalyzerTest.java @@ -0,0 +1,164 @@ +package dev.dnpm.analyzer; + +import dev.dnpm.dto.EcogStatusWithDate; +import dev.dnpm.services.strahlentherapie.StrahlentherapieService; +import dev.dnpm.services.systemtherapie.SystemtherapieService; +import de.itc.onkostar.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TherapieMitEcogAnalyzerTest { + + private IOnkostarApi onkostarApi; + + private StrahlentherapieService strahlentherapieService; + + private SystemtherapieService systemtherapieService; + + private TherapieMitEcogAnalyzer therapieMitEcogAnalyzer; + + private Disease dummyDisease(int id, Date diagnosisDate) { + var disease = new Disease(onkostarApi); + disease.setId(id); + disease.setDiagnosisDate(diagnosisDate); + return disease; + } + + private Date daysPassed(int days) { + return Date.from(Instant.now().minus(days, ChronoUnit.DAYS)); + } + + @BeforeEach + void setUp( + @Mock IOnkostarApi onkostarApi, + @Mock StrahlentherapieService strahlentherapieService, + @Mock SystemtherapieService systemtherapieService + ) { + this.onkostarApi = onkostarApi; + this.strahlentherapieService = strahlentherapieService; + this.systemtherapieService = systemtherapieService; + this.therapieMitEcogAnalyzer = new TherapieMitEcogAnalyzer(onkostarApi, strahlentherapieService, systemtherapieService); + } + + @Test + void shouldInsertNewEcogStatus() throws Exception { + final var diagnosisDate = daysPassed(7); + final var ecogDate = daysPassed(1); + final var procedureDate = daysPassed(1); + + doAnswer(invocationOnMock -> List.of(new EcogStatusWithDate(ecogDate, "0"))) + .when(systemtherapieService).ecogStatus(any(Patient.class)); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setStartDate(procedureDate); + procedure.setEditState(ProcedureEditStateType.COMPLETED); + procedure.setPatientId(1); + procedure.setPatient(patient); + procedure.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + doAnswer(invocationOnMock -> List.of(dummyDisease(42, diagnosisDate))).when(this.onkostarApi).getDiseasesByPatientId(anyInt()); + + doAnswer(invocationOnMock -> List.of(procedure)).when(onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + therapieMitEcogAnalyzer.analyze(procedure, dummyDisease(10, diagnosisDate)); + + var idCaptor = ArgumentCaptor.forClass(Integer.class); + var formNameCaptor = ArgumentCaptor.forClass(String.class); + verify(onkostarApi, times(1)).getProceduresForDiseaseByForm(idCaptor.capture(), formNameCaptor.capture()); + assertThat(idCaptor.getValue()).isEqualTo(42); + assertThat(formNameCaptor.getValue()).isEqualTo("DNPM Klinik/Anamnese"); + + verify(onkostarApi, times(1)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void shouldNotModifyEcogStatusIfNoCompletedSystemTherapy() throws Exception { + final var diagnosisDate = daysPassed(7); + final var procedureDate = daysPassed(1); + + doAnswer(invocationOnMock -> List.of()) + .when(systemtherapieService).ecogStatus(any(Patient.class)); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setStartDate(procedureDate); + procedure.setEditState(ProcedureEditStateType.COMPLETED); + procedure.setPatientId(1); + procedure.setPatient(patient); + procedure.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + therapieMitEcogAnalyzer.analyze(procedure, dummyDisease(10, diagnosisDate)); + + verify(onkostarApi, times(0)).getProceduresForDiseaseByForm(anyInt(), anyString()); + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void shouldNotIncludeEcogStatusBeforeDiagnosisDate() throws Exception { + final var diagnosisDate = daysPassed(7); + final var ecogDate = daysPassed(28); + final var procedureDate = daysPassed(1); + + doAnswer(invocationOnMock -> List.of(new EcogStatusWithDate(ecogDate, "0"))) + .when(systemtherapieService).ecogStatus(any(Patient.class)); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setStartDate(procedureDate); + procedure.setEditState(ProcedureEditStateType.COMPLETED); + procedure.setPatientId(1); + procedure.setPatient(patient); + procedure.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + therapieMitEcogAnalyzer.analyze(procedure, dummyDisease(10, diagnosisDate)); + + verify(onkostarApi, times(0)).getProceduresForDiseaseByForm(anyInt(), anyString()); + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void shouldRequestEcogFromStrahlentherapieAndSystemtherapie() { + final var diagnosisDate = daysPassed(7); + final var procedureDate = daysPassed(1); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var procedure = new Procedure(onkostarApi); + procedure.setId(1000); + procedure.setStartDate(procedureDate); + procedure.setEditState(ProcedureEditStateType.COMPLETED); + procedure.setPatientId(1); + procedure.setPatient(patient); + procedure.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + therapieMitEcogAnalyzer.analyze(procedure, dummyDisease(10, diagnosisDate)); + + verify(strahlentherapieService, times(1)).ecogStatus(any()); + verify(systemtherapieService, times(1)).ecogStatus(any()); + } + +} diff --git a/src/test/java/dev/dnpm/analyzer/TherapieplanAnalyzerTest.java b/src/test/java/dev/dnpm/analyzer/TherapieplanAnalyzerTest.java new file mode 100644 index 0000000..2f22e37 --- /dev/null +++ b/src/test/java/dev/dnpm/analyzer/TherapieplanAnalyzerTest.java @@ -0,0 +1,96 @@ +package dev.dnpm.analyzer; + +import dev.dnpm.security.DelegatingDataBasedPermissionEvaluator; +import dev.dnpm.security.PermissionType; +import dev.dnpm.services.FormService; +import dev.dnpm.services.mtb.MtbService; +import dev.dnpm.services.therapieplan.MultipleMtbTherapieplanService; +import dev.dnpm.services.therapieplan.TherapieplanService; +import dev.dnpm.services.therapieplan.TherapieplanServiceFactory; +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TherapieplanAnalyzerTest { + + @Mock + private IOnkostarApi onkostarApi; + + @Mock + private FormService formService; + + @Mock + private TherapieplanServiceFactory therapieplanServiceFactory; + + @Mock + private TherapieplanService therapieplanService; + + @Mock + private MtbService mtbService; + + @Mock + private DelegatingDataBasedPermissionEvaluator permissionEvaluator; + + private TherapieplanAnalyzer therapieplanAnalyzer; + + @BeforeEach + void setUp() { + this.therapieplanAnalyzer = new TherapieplanAnalyzer(therapieplanServiceFactory, mtbService, permissionEvaluator); + } + + @Test + void shouldRunServiceMethodsOnAnalyzeCalled() { + when(this.therapieplanServiceFactory.currentUsableInstance()) + .thenReturn(new MultipleMtbTherapieplanService(onkostarApi, formService)); + + this.therapieplanAnalyzer.analyze(new Procedure(onkostarApi), null); + + verify(this.therapieplanServiceFactory, times(1)).currentUsableInstance(); + } + + @Test + void shouldRequestProtokollauszug() { + doAnswer(invocationOnMock -> { + var procedure = new Procedure(onkostarApi); + procedure.setValue("referstemtb", new Item("referstemtb", 2345)); + return List.of(procedure); + }).when(this.therapieplanService).findReferencedMtbs(anyInt()); + + when(this.therapieplanServiceFactory.currentUsableInstance()) + .thenReturn(therapieplanService); + + when(this.permissionEvaluator.hasPermission(any(), anyInt(), anyString(), any(PermissionType.class))).thenReturn(true); + + var input = Map.of("id", (Object) 1234); + this.therapieplanAnalyzer.getProtokollauszug(input); + + var captor = ArgumentCaptor.forClass(List.class); + verify(mtbService, times(1)).getProtocol(captor.capture()); + assertThat(captor.getValue()).hasSize(1); + } + + @Test + void shouldNotRequestProtokollauszugDueToNoPermission() { + when(this.permissionEvaluator.hasPermission(any(), anyInt(), anyString(), any(PermissionType.class))) + .thenReturn(false); + + var input = Map.of("id", (Object) 1234); + this.therapieplanAnalyzer.getProtokollauszug(input); + + verify(mtbService, times(0)).getProtocol(anyList()); + } + +} diff --git a/src/test/java/dev/dnpm/config/PluginConfigurationTest.java b/src/test/java/dev/dnpm/config/PluginConfigurationTest.java new file mode 100644 index 0000000..a71630f --- /dev/null +++ b/src/test/java/dev/dnpm/config/PluginConfigurationTest.java @@ -0,0 +1,46 @@ +package dev.dnpm.config; + +import dev.dnpm.services.FormService; +import dev.dnpm.services.SettingsService; +import dev.dnpm.services.therapieplan.TherapieplanServiceFactory; +import dev.dnpm.services.consent.ConsentManagerServiceFactory; +import de.itc.onkostar.api.IOnkostarApi; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class PluginConfigurationTest { + + @Mock + private IOnkostarApi onkostarApi; + + @Mock + private SettingsService settingsService; + + @Mock + private FormService formService; + + private PluginConfiguration configuration; + + @BeforeEach + void setup() { + this.configuration = new PluginConfiguration(); + } + + @Test + void testShouldReturnConsentManagerServiceFactory() { + var actual = this.configuration.consentManagerServiceFactory(onkostarApi); + assertThat(actual).isInstanceOf(ConsentManagerServiceFactory.class); + } + + @Test + void testShouldReturnTherapieplanServiceFactory() { + var actual = this.configuration.therapieplanServiceFactory(onkostarApi, settingsService, formService); + assertThat(actual).isInstanceOf(TherapieplanServiceFactory.class); + } +} diff --git a/src/test/java/dev/dnpm/dto/VariantTest.java b/src/test/java/dev/dnpm/dto/VariantTest.java new file mode 100644 index 0000000..f699f0c --- /dev/null +++ b/src/test/java/dev/dnpm/dto/VariantTest.java @@ -0,0 +1,103 @@ +package dev.dnpm.dto; + +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class VariantTest { + + @Test + void testShouldMapVariantFromProcedureForSimpleVariant() { + var procedure = new Procedure(null); + procedure.setId(12345); + procedure.setFormName("OS.Molekulargenetische Untersuchung"); + + procedure.setValue("Ergebnis", new Item("Ergebnis", "P")); + procedure.setValue("Untersucht", new Item("Untersucht", "BRAF")); + procedure.setValue("ExonInt", new Item("ExonInt", 123)); + procedure.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + + var actual = Variant.fromProcedure(procedure); + + assertThat(actual).isPresent(); + assertThat(actual.get().getId()).isEqualTo(12345); + assertThat(actual.get().getErgebnis()).isEqualTo("Einfache Variante (Mutation)"); + assertThat(actual.get().getGen()).isEqualTo("BRAF"); + assertThat(actual.get().getExon()).isEqualTo("123"); + assertThat(actual.get().getPathogenitaetsklasse()).isEqualTo("2"); + } + + @Test + void testShouldMapVariantFromProcedureForCopyNumberVariation() { + var procedure = new Procedure(null); + procedure.setId(12345); + procedure.setFormName("OS.Molekulargenetische Untersuchung"); + + procedure.setValue("Ergebnis", new Item("Ergebnis", "CNV")); + procedure.setValue("Untersucht", new Item("Untersucht", "BRAF")); + procedure.setValue("ExonInt", new Item("ExonInt", 123)); + procedure.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + + var actual = Variant.fromProcedure(procedure); + + assertThat(actual).isPresent(); + assertThat(actual.get().getId()).isEqualTo(12345); + assertThat(actual.get().getErgebnis()).isEqualTo("Copy Number Variation (CNV)"); + assertThat(actual.get().getGen()).isEqualTo("BRAF"); + assertThat(actual.get().getExon()).isEqualTo("123"); + assertThat(actual.get().getPathogenitaetsklasse()).isEqualTo("2"); + } + + @Test + void testShouldMapVariantFromProcedureForFusion() { + var procedure = new Procedure(null); + procedure.setId(12345); + procedure.setFormName("OS.Molekulargenetische Untersuchung"); + + procedure.setValue("Ergebnis", new Item("Ergebnis", "F")); + procedure.setValue("Untersucht", new Item("Untersucht", "BRAF")); + procedure.setValue("ExonInt", new Item("ExonInt", 123)); + procedure.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + + var actual = Variant.fromProcedure(procedure); + + assertThat(actual).isPresent(); + assertThat(actual.get().getId()).isEqualTo(12345); + assertThat(actual.get().getErgebnis()).isEqualTo("Fusion (Translokation Inversion Insertion)"); + assertThat(actual.get().getGen()).isEqualTo("BRAF"); + assertThat(actual.get().getExon()).isEqualTo("123"); + assertThat(actual.get().getPathogenitaetsklasse()).isEqualTo("2"); + } + + @Test + void testShouldNotMapVariantFromProcedureForUnknownVariant() { + var procedure = new Procedure(null); + procedure.setId(12345); + procedure.setFormName("OS.Molekulargenetische Untersuchung"); + + procedure.setValue("Ergebnis", new Item("Ergebnis", "X")); + procedure.setValue("Untersucht", new Item("Untersucht", "BRAF")); + procedure.setValue("ExonInt", new Item("ExonInt", 123)); + procedure.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + + var actual = Variant.fromProcedure(procedure); + + assertThat(actual).isEmpty(); + } + + @Test + void testShouldNotMapVariantFromUnknownProcedureForm() { + var procedure = new Procedure(null); + procedure.setId(12345); + procedure.setFormName("ABC.Irgendwas"); + + procedure.setValue("Testfeld", new Item("Testfeld", "T")); + + var actual = Variant.fromProcedure(procedure); + + assertThat(actual).isEmpty(); + } + +} diff --git a/src/test/java/dev/dnpm/security/DelegatingDataBasedPermissionEvaluatorTest.java b/src/test/java/dev/dnpm/security/DelegatingDataBasedPermissionEvaluatorTest.java new file mode 100644 index 0000000..c1e71db --- /dev/null +++ b/src/test/java/dev/dnpm/security/DelegatingDataBasedPermissionEvaluatorTest.java @@ -0,0 +1,122 @@ +package dev.dnpm.security; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Patient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DelegatingDataBasedPermissionEvaluatorTest { + + private IOnkostarApi onkostarApi; + + private PersonPoolBasedPermissionEvaluator personPoolBasedPermissionEvaluator; + + private FormBasedPermissionEvaluator formBasedPermissionEvaluator; + + private DelegatingDataBasedPermissionEvaluator delegatingDataBasedPermissionEvaluator; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock PersonPoolBasedPermissionEvaluator personPoolBasedPermissionEvaluator, + @Mock FormBasedPermissionEvaluator formBasedPermissionEvaluator + ) { + this.onkostarApi = onkostarApi; + this.personPoolBasedPermissionEvaluator = personPoolBasedPermissionEvaluator; + this.formBasedPermissionEvaluator = formBasedPermissionEvaluator; + + this.delegatingDataBasedPermissionEvaluator = new DelegatingDataBasedPermissionEvaluator( + List.of(personPoolBasedPermissionEvaluator, formBasedPermissionEvaluator) + ); + } + + @Test + void testShouldGrantPermissionIfAllDelegatedPermissionEvaluatorsGrantsAccessByObject() { + when(personPoolBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))).thenReturn(true); + when(formBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))).thenReturn(true); + + var actual = delegatingDataBasedPermissionEvaluator.hasPermission(new DummyAuthentication(), new Patient(this.onkostarApi), PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldGrantPermissionIfAllDelegatedPermissionEvaluatorsGrantsAccessByIdAndType() { + when(personPoolBasedPermissionEvaluator.hasPermission(any(), anyInt(), anyString(), any(PermissionType.class))).thenReturn(true); + when(formBasedPermissionEvaluator.hasPermission(any(), anyInt(), anyString(), any(PermissionType.class))).thenReturn(true); + + var actual = delegatingDataBasedPermissionEvaluator.hasPermission(new DummyAuthentication(), 123, "Patient", PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldDenyPermissionIfAtLeastOneDelegatedPermissionEvaluatorsDeniesAccessByObject() { + when(personPoolBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))).thenReturn(true); + when(formBasedPermissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))).thenReturn(false); + + var actual = delegatingDataBasedPermissionEvaluator.hasPermission(new DummyAuthentication(), new Patient(this.onkostarApi), PermissionType.READ); + + assertThat(actual).isFalse(); + } + + @Test + void testShouldDenyPermissionIfAtLeastOneDelegatedPermissionEvaluatorsDeniesAccessByIdAndType() { + when(personPoolBasedPermissionEvaluator.hasPermission(any(), anyInt(), anyString(), any(PermissionType.class))).thenReturn(false); + + var actual = delegatingDataBasedPermissionEvaluator.hasPermission(new DummyAuthentication(), 123, "Patient", PermissionType.READ); + + assertThat(actual).isFalse(); + } + +} + +class DummyAuthentication implements Authentication { + @Override + public String getName() { + return "dummy"; + } + + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return null; + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public Object getPrincipal() { + return null; + } + + @Override + public boolean isAuthenticated() { + return false; + } + + @Override + public void setAuthenticated(boolean b) throws IllegalArgumentException { + + } +}
\ No newline at end of file diff --git a/src/test/java/dev/dnpm/security/FormBasedPermissionEvaluatorTest.java b/src/test/java/dev/dnpm/security/FormBasedPermissionEvaluatorTest.java new file mode 100644 index 0000000..2ce938f --- /dev/null +++ b/src/test/java/dev/dnpm/security/FormBasedPermissionEvaluatorTest.java @@ -0,0 +1,112 @@ +package dev.dnpm.security; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.core.Authentication; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class FormBasedPermissionEvaluatorTest { + + private IOnkostarApi onkostarApi; + + private Authentication dummyAuthentication; + + private SecurityService securityService; + + private FormBasedPermissionEvaluator permissionEvaluator; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock SecurityService securityService, + @Mock DummyAuthentication dummyAuthentication + ) { + this.onkostarApi = onkostarApi; + this.dummyAuthentication = dummyAuthentication; + this.securityService = securityService; + + this.permissionEvaluator = new FormBasedPermissionEvaluator( + onkostarApi, securityService + ); + } + + @Test + void testShouldGrantPermissionByProcedure() { + when(securityService.getFormNamesForPermission(any(Authentication.class), any(PermissionType.class))).thenReturn(List.of("OS.Form2", "OS.Form3", "OS.Form5")); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form2"); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + assertThat(actual).isTrue(); + } + + @Test + void testShouldGrantPermissionByProcedureId() { + when(securityService.getFormNamesForPermission(any(Authentication.class), any(PermissionType.class))).thenReturn(List.of("OS.Form2", "OS.Form3", "OS.Form5")); + + doAnswer(invocationOnMock -> { + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form2"); + return object; + }).when(onkostarApi).getProcedure(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, PersonPoolBasedPermissionEvaluator.PROCEDURE, PermissionType.READ); + assertThat(actual).isTrue(); + } + + @Test + void testShouldDenyPermissionByProcedure() { + when(securityService.getFormNamesForPermission(any(Authentication.class), any(PermissionType.class))).thenReturn(List.of("OS.Form2", "OS.Form3", "OS.Form5")); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + assertThat(actual).isFalse(); + } + + @Test + void testShouldDenyPermissionByProcedureId() { + when(securityService.getFormNamesForPermission(any(Authentication.class), any(PermissionType.class))).thenReturn(List.of("OS.Form2", "OS.Form3", "OS.Form5")); + + doAnswer(invocationOnMock -> { + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + return object; + }).when(onkostarApi).getProcedure(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, PersonPoolBasedPermissionEvaluator.PROCEDURE, PermissionType.READ); + assertThat(actual).isFalse(); + } + + @Test + void testShouldVoteForPermissionToPatient() { + var object = new Patient(onkostarApi); + object.setPersonPoolCode("Pool1"); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + assertThat(actual).isTrue(); + } + + @Test + void testShouldVoteForPermissionToIdOfTypeProcedure() { + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, FormBasedPermissionEvaluator.PATIENT, PermissionType.READ); + assertThat(actual).isTrue(); + } + +} diff --git a/src/test/java/dev/dnpm/security/FormBasedSecurityAspectsTest.java b/src/test/java/dev/dnpm/security/FormBasedSecurityAspectsTest.java new file mode 100644 index 0000000..ee57688 --- /dev/null +++ b/src/test/java/dev/dnpm/security/FormBasedSecurityAspectsTest.java @@ -0,0 +1,131 @@ +package dev.dnpm.security; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class FormBasedSecurityAspectsTest { + + private DummyClass dummyClass; + + private IOnkostarApi onkostarApi; + + private FormBasedPermissionEvaluator permissionEvaluator; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock FormBasedPermissionEvaluator permissionEvaluator + ) { + this.onkostarApi = onkostarApi; + this.permissionEvaluator = permissionEvaluator; + + // Create proxied instance of DummyClass as done within Onkostar using Spring AOP + var dummyClass = new DummyClass(onkostarApi); + AspectJProxyFactory factory = new AspectJProxyFactory(dummyClass); + FormBasedSecurityAspects securityAspects = new FormBasedSecurityAspects(this.permissionEvaluator); + factory.addAspect(securityAspects); + this.dummyClass = factory.getProxy(); + } + + @Test + void testShouldAllowSecuredMethodCallWithPatientParam() { + this.dummyClass.methodWithPatientParam(new Patient(onkostarApi)); + verify(onkostarApi, times(1)).savePatient(any(Patient.class)); + } + + @Test + void testShouldPreventSecuredMethodCallWithProcedureParam() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithProcedureParam(new Procedure(onkostarApi)) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithProcedureParam() throws Exception { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(true); + + this.dummyClass.methodWithProcedureParam(new Procedure(onkostarApi)); + + verify(onkostarApi, times(1)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void testShouldAllowSecuredMethodCallWithPatientReturnValue() { + var actual = this.dummyClass.methodWithPatientReturnValue(1); + assertThat(actual).isNotNull(); + } + + @Test + void testShouldPreventSecuredMethodCallWithProcedureReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithProcedureReturnValue(1) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithProcedureReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(true); + + var actual = this.dummyClass.methodWithProcedureReturnValue(1); + + assertThat(actual).isNotNull(); + } + + private static class DummyClass { + + private final IOnkostarApi onkostarApi; + + DummyClass(final IOnkostarApi onkostarApi) { + this.onkostarApi = onkostarApi; + } + + @FormSecured + public void methodWithPatientParam(Patient patient) { + this.onkostarApi.savePatient(patient); + } + + @FormSecured + public void methodWithProcedureParam(Procedure procedure) throws Exception { + this.onkostarApi.saveProcedure(procedure, false); + } + + @FormSecuredResult + public Patient methodWithPatientReturnValue(int id) { + var patient = new Patient(this.onkostarApi); + patient.setId(id); + return patient; + } + + @FormSecuredResult + public Procedure methodWithProcedureReturnValue(int id) { + var procedure = new Procedure(this.onkostarApi); + procedure.setId(id); + return procedure; + } + } + +} diff --git a/src/test/java/dev/dnpm/security/PersonPoolBasedPermissionEvaluatorTest.java b/src/test/java/dev/dnpm/security/PersonPoolBasedPermissionEvaluatorTest.java new file mode 100644 index 0000000..a5f39e3 --- /dev/null +++ b/src/test/java/dev/dnpm/security/PersonPoolBasedPermissionEvaluatorTest.java @@ -0,0 +1,160 @@ +package dev.dnpm.security; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.core.Authentication; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class PersonPoolBasedPermissionEvaluatorTest { + + private IOnkostarApi onkostarApi; + + private Authentication dummyAuthentication; + + private PersonPoolBasedPermissionEvaluator permissionEvaluator; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock SecurityService securityService, + @Mock DummyAuthentication dummyAuthentication + ) { + this.onkostarApi = onkostarApi; + this.dummyAuthentication = dummyAuthentication; + + this.permissionEvaluator = new PersonPoolBasedPermissionEvaluator( + onkostarApi, securityService + ); + + when(securityService.getPersonPoolIdsForPermission(any(Authentication.class), any(PermissionType.class))).thenReturn(List.of("Pool2", "Pool3", "Pool5")); + } + + @Test + void testShouldGrantPermissionByPatientObject() { + var object = new Patient(onkostarApi); + object.setPersonPoolCode("Pool2"); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldGrantPermissionByPatientIdAndType() { + doAnswer(invocationOnMock -> { + var object = new Patient(onkostarApi); + object.setPersonPoolCode("Pool2"); + return object; + }).when(onkostarApi).getPatient(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, PersonPoolBasedPermissionEvaluator.PATIENT, PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldDenyPermissionByPatientObject() { + var object = new Patient(onkostarApi); + object.setPersonPoolCode("Pool1"); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + + assertThat(actual).isFalse(); + } + + @Test + void testShouldDenyPermissionByPatientIdAndType() { + doAnswer(invocationOnMock -> { + var object = new Patient(onkostarApi); + object.setPersonPoolCode("Pool1"); + return object; + }).when(onkostarApi).getPatient(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, PersonPoolBasedPermissionEvaluator.PATIENT, PermissionType.READ); + + assertThat(actual).isFalse(); + } + + @Test + void testShouldGrantPermissionByProcedureObject() { + var patient = new Patient(onkostarApi); + patient.setId(1); + patient.setPersonPoolCode("Pool2"); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + object.setPatient(patient); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldGrantPermissionByProcedureIdAndType() { + doAnswer(invocationOnMock -> { + var patient = new Patient(onkostarApi); + patient.setId(1); + patient.setPersonPoolCode("Pool2"); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + object.setPatient(patient); + + return object; + }).when(onkostarApi).getProcedure(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 456, PersonPoolBasedPermissionEvaluator.PROCEDURE, PermissionType.READ); + + assertThat(actual).isTrue(); + } + + @Test + void testShouldDenyPermissionByProcedureObject() { + var patient = new Patient(onkostarApi); + patient.setId(1); + patient.setPersonPoolCode("Pool1"); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + object.setPatient(patient); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, object, PermissionType.READ); + + assertThat(actual).isFalse(); + } + + @Test + void testShouldDenyPermissionByProcedureIdAndType() { + doAnswer(invocationOnMock -> { + var patient = new Patient(onkostarApi); + patient.setId(1); + patient.setPersonPoolCode("Pool1"); + + var object = new Procedure(onkostarApi); + object.setFormName("OS.Form1"); + object.setPatient(patient); + + return object; + }).when(onkostarApi).getProcedure(anyInt()); + + var actual = permissionEvaluator.hasPermission(this.dummyAuthentication, 123, PersonPoolBasedPermissionEvaluator.PROCEDURE, PermissionType.READ); + + assertThat(actual).isFalse(); + } + +}
\ No newline at end of file diff --git a/src/test/java/dev/dnpm/security/PersonPoolBasedSecurityAspectsTest.java b/src/test/java/dev/dnpm/security/PersonPoolBasedSecurityAspectsTest.java new file mode 100644 index 0000000..333a8f3 --- /dev/null +++ b/src/test/java/dev/dnpm/security/PersonPoolBasedSecurityAspectsTest.java @@ -0,0 +1,163 @@ +package dev.dnpm.security; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class PersonPoolBasedSecurityAspectsTest { + + private DummyClass dummyClass; + + private IOnkostarApi onkostarApi; + + private PersonPoolBasedPermissionEvaluator permissionEvaluator; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi, + @Mock PersonPoolBasedPermissionEvaluator permissionEvaluator + ) { + this.onkostarApi = onkostarApi; + this.permissionEvaluator = permissionEvaluator; + + // Create proxied instance of DummyClass as done within Onkostar using Spring AOP + var dummyClass = new DummyClass(onkostarApi); + AspectJProxyFactory factory = new AspectJProxyFactory(dummyClass); + PersonPoolBasedSecurityAspects securityAspects = new PersonPoolBasedSecurityAspects(this.permissionEvaluator); + factory.addAspect(securityAspects); + this.dummyClass = factory.getProxy(); + } + + @Test + void testShouldPreventSecuredMethodCallWithPatientParam() { + when(this.permissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithPatientParam(new Patient(onkostarApi)) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithPatientParam() { + when(this.permissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(true); + + this.dummyClass.methodWithPatientParam(new Patient(onkostarApi)); + + verify(onkostarApi, times(1)).savePatient(any(Patient.class)); + } + + @Test + void testShouldPreventSecuredMethodCallWithProcedureParam() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithProcedureParam(new Procedure(onkostarApi)) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithProcedureParam() throws Exception { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(true); + + this.dummyClass.methodWithProcedureParam(new Procedure(onkostarApi)); + + verify(onkostarApi, times(1)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void testShouldPreventSecuredMethodCallWithPatientReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithPatientReturnValue(1) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithPatientReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Patient.class), any(PermissionType.class))) + .thenReturn(true); + + var actual = this.dummyClass.methodWithPatientReturnValue(1); + + assertThat(actual).isNotNull(); + } + + @Test + void testShouldPreventSecuredMethodCallWithProcedureReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(false); + + var exception = assertThrows( + Exception.class, + () -> this.dummyClass.methodWithProcedureReturnValue(1) + ); + assertThat(exception).isExactlyInstanceOf(IllegalSecuredObjectAccessException.class); + } + + @Test + void testShouldAllowSecuredMethodCallWithProcedureReturnValue() { + when(this.permissionEvaluator.hasPermission(any(), any(Procedure.class), any(PermissionType.class))) + .thenReturn(true); + + var actual = this.dummyClass.methodWithProcedureReturnValue(1); + + assertThat(actual).isNotNull(); + } + + private static class DummyClass { + + private final IOnkostarApi onkostarApi; + + DummyClass(final IOnkostarApi onkostarApi) { + this.onkostarApi = onkostarApi; + } + + @PersonPoolSecured + public void methodWithPatientParam(Patient patient) { + this.onkostarApi.savePatient(patient); + } + + @PersonPoolSecured + public void methodWithProcedureParam(Procedure procedure) throws Exception { + this.onkostarApi.saveProcedure(procedure, false); + } + + @PersonPoolSecuredResult + public Patient methodWithPatientReturnValue(int id) { + var patient = new Patient(this.onkostarApi); + patient.setId(id); + return patient; + } + + @PersonPoolSecuredResult + public Procedure methodWithProcedureReturnValue(int id) { + var procedure = new Procedure(this.onkostarApi); + procedure.setId(id); + return procedure; + } + } + +} diff --git a/src/test/java/dev/dnpm/services/SettingsServiceTest.java b/src/test/java/dev/dnpm/services/SettingsServiceTest.java new file mode 100644 index 0000000..c5fd26e --- /dev/null +++ b/src/test/java/dev/dnpm/services/SettingsServiceTest.java @@ -0,0 +1,60 @@ +package dev.dnpm.services; + +import dev.dnpm.database.SettingsRepository; +import de.itc.db.dnpm.Setting; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doAnswer; + +@ExtendWith(MockitoExtension.class) +class SettingsServiceTest { + + @Mock + private SettingsRepository settingsRepository; + + private SettingsService service; + + @BeforeEach + void setUp() { + this.service = new SettingsService(settingsRepository); + } + + @Test + void shouldReturnSID() { + doAnswer(invocationOnMock -> { + var name = invocationOnMock.getArgument(0, String.class); + if (null != name && name.equals("SID")) { + return new Setting(1L, "SID", "12345"); + } + return null; + }).when(settingsRepository).findByName(anyString()); + + var actual = service.getSID(); + assertThat(actual) + .isPresent() + .contains("12345"); + } + + @Test + void shouldReturnSIDByName() { + doAnswer(invocationOnMock -> { + var name = invocationOnMock.getArgument(0, String.class); + if (null != name && name.equals("SID")) { + return new Setting(1L, "SID", "12345"); + } + return null; + }).when(settingsRepository).findByName(anyString()); + + var actual = service.getSetting("SID"); + assertThat(actual) + .isPresent() + .contains("12345"); + } + +} diff --git a/src/test/java/dev/dnpm/services/StudieTest.java b/src/test/java/dev/dnpm/services/StudieTest.java new file mode 100644 index 0000000..debf6b9 --- /dev/null +++ b/src/test/java/dev/dnpm/services/StudieTest.java @@ -0,0 +1,55 @@ +package dev.dnpm.services; + +import dev.dnpm.dto.Studie; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class StudieTest { + + @Test + void shouldDetectStudieWithNctNumber() { + var studie = new Studie( + "Kat 1", + 1, + null, + "Nct-12345678", + "Teststudie 1", + "Teststudie 1", + true + ); + + assertThat(studie.getType()).isEqualTo(Studie.Type.NCT); + } + + @Test + void shouldDetectStudieWithEudraCtNumber() { + var studie = new Studie( + "Kat 1", + 1, + null, + "2023-012345-12", + "Teststudie 1", + "Teststudie 1", + true + ); + + assertThat(studie.getType()).isEqualTo(Studie.Type.EUDRA_CT); + } + + @Test + void shouldReturnStudieWithUnknownNumberScheme() { + var studie = new Studie( + "Kat 1", + 1, + "teststudie1", + null, + "Teststudie 1", + "Teststudie 1", + true + ); + + assertThat(studie.getType()).isEqualTo(Studie.Type.UNKNOWN); + } + +} diff --git a/src/test/java/dev/dnpm/services/consent/ConsentManagerServiceFactoryTest.java b/src/test/java/dev/dnpm/services/consent/ConsentManagerServiceFactoryTest.java new file mode 100644 index 0000000..b0d76e3 --- /dev/null +++ b/src/test/java/dev/dnpm/services/consent/ConsentManagerServiceFactoryTest.java @@ -0,0 +1,50 @@ +package dev.dnpm.services.consent; + +import de.itc.onkostar.api.IOnkostarApi; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ConsentManagerServiceFactoryTest { + + private IOnkostarApi onkostarApi; + + private ConsentManagerServiceFactory consentManagerServiceFactory; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.consentManagerServiceFactory = new ConsentManagerServiceFactory(onkostarApi); + } + + private static Set<Map.Entry<String, Class<? extends ConsentManagerService>>> expectedMappings() { + return Map.ofEntries( + Map.entry("MR.Consent", MrConsentManagerService.class), + Map.entry("Excel-Formular", UkwConsentManagerService.class) + ).entrySet(); + } + + @ParameterizedTest + @MethodSource("expectedMappings") + void testShouldMapFormNameToService(Map.Entry<String, Class<?>> expectedMapping) { + when(onkostarApi.getGlobalSetting(anyString())).thenReturn(expectedMapping.getKey()); + + var actual = consentManagerServiceFactory.currentUsableInstance(); + + assertThat(actual).isExactlyInstanceOf(expectedMapping.getValue()); + } + +} diff --git a/src/test/java/dev/dnpm/services/consent/MrConsentManagerServiceTest.java b/src/test/java/dev/dnpm/services/consent/MrConsentManagerServiceTest.java new file mode 100644 index 0000000..0f06dc4 --- /dev/null +++ b/src/test/java/dev/dnpm/services/consent/MrConsentManagerServiceTest.java @@ -0,0 +1,59 @@ +package dev.dnpm.services.consent; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Procedure; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.type.Type; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class MrConsentManagerServiceTest { + + private IOnkostarApi onkostarApi; + + private MrConsentManagerService service; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.service = new MrConsentManagerService(onkostarApi); + } + + @Test + void testShouldCreateSqlQueriesWithRelatedEntityIds() { + var sessionFactory = mock(SessionFactory.class); + var session = mock(Session.class); + var query = mock(SQLQuery.class); + + when(onkostarApi.getSessionFactory()).thenReturn(sessionFactory); + when(sessionFactory.getCurrentSession()).thenReturn(session); + when(session.createSQLQuery(anyString())).thenReturn(query); + when(query.addScalar(anyString(), any(Type.class))).thenReturn(query); + when(query.uniqueResult()).thenReturn(""); + + var dummyProzedur = new Procedure(this.onkostarApi); + dummyProzedur.setId(111); + dummyProzedur.setPatientId(123); + + this.service.applyConsent(dummyProzedur); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(session, times(2)).createSQLQuery(argumentCaptor.capture()); + assertThat(argumentCaptor.getAllValues()).hasSize(2); + assertThat(argumentCaptor.getAllValues().get(0)).contains("where entity_id = '111'"); + assertThat(argumentCaptor.getAllValues().get(1)).contains("WHERE patient_id = 123 AND geloescht = 0"); + } + +} diff --git a/src/test/java/dev/dnpm/services/consent/UkwConsentManagerServiceTest.java b/src/test/java/dev/dnpm/services/consent/UkwConsentManagerServiceTest.java new file mode 100644 index 0000000..28a76e0 --- /dev/null +++ b/src/test/java/dev/dnpm/services/consent/UkwConsentManagerServiceTest.java @@ -0,0 +1,138 @@ +package dev.dnpm.services.consent; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Date; +import java.time.Instant; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UkwConsentManagerServiceTest { + + private IOnkostarApi onkostarApi; + + private UkwConsentManagerService service; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.service = new UkwConsentManagerService(onkostarApi); + } + + @Test + void testShouldSkipUpdateRelatedDnpmKlinikAnamneseFormIfNoConsentAvailable() throws Exception { + + var excelForm = new Procedure(this.onkostarApi); + excelForm.setId(111); + excelForm.setPatientId(123); + excelForm.setValue("refdnpmklinikanamnese", new Item("refdnpmklinikanamnese", 2)); + + var dnpmKlinikAnamneseForm = new Procedure(this.onkostarApi); + dnpmKlinikAnamneseForm.setId(2); + dnpmKlinikAnamneseForm.setPatientId(123); + + when(onkostarApi.getProcedure(anyInt())).thenReturn(dnpmKlinikAnamneseForm); + + this.service.applyConsent(excelForm); + + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void testShouldSkipUpdateRelatedDnpmKlinikAnamneseFormIfNoConsentDateAvailable() throws Exception { + + var consentSubForm = new Procedure(this.onkostarApi); + consentSubForm.setId(1); + consentSubForm.setPatientId(123); + consentSubForm.setValue("status", new Item("status", "accepted")); + + + var excelForm = new Procedure(this.onkostarApi); + excelForm.setId(111); + excelForm.setPatientId(123); + excelForm.setValue("refdnpmklinikanamnese", new Item("refdnpmklinikanamnese", 2)); + excelForm.addSubProcedure("ufdnpmconsent", consentSubForm); + + var dnpmKlinikAnamneseForm = new Procedure(this.onkostarApi); + dnpmKlinikAnamneseForm.setId(2); + dnpmKlinikAnamneseForm.setPatientId(123); + + when(onkostarApi.getProcedure(anyInt())).thenReturn(dnpmKlinikAnamneseForm); + + this.service.applyConsent(excelForm); + + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void testShouldSkipUpdateRelatedDnpmKlinikAnamneseFormIfNoConsentValueAvailable() throws Exception { + + var consentSubForm = new Procedure(this.onkostarApi); + consentSubForm.setId(1); + consentSubForm.setPatientId(123); + consentSubForm.setStartDate(Date.from(Instant.parse("2023-04-03T12:00:00Z"))); + consentSubForm.setValue("datum", new Item("datum", Date.from(Instant.parse("2023-04-03T12:00:00Z")))); + + var excelForm = new Procedure(this.onkostarApi); + excelForm.setId(111); + excelForm.setPatientId(123); + excelForm.setValue("refdnpmklinikanamnese", new Item("refdnpmklinikanamnese", 2)); + excelForm.addSubProcedure("ufdnpmconsent", consentSubForm); + + var dnpmKlinikAnamneseForm = new Procedure(this.onkostarApi); + dnpmKlinikAnamneseForm.setId(2); + dnpmKlinikAnamneseForm.setPatientId(123); + + when(onkostarApi.getProcedure(anyInt())).thenReturn(dnpmKlinikAnamneseForm); + + this.service.applyConsent(excelForm); + + verify(onkostarApi, times(0)).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void testShouldUpdateRelatedDnpmKlinikAnamneseFormOnFormSave() throws Exception { + + var consentSubForm = new Procedure(this.onkostarApi); + consentSubForm.setId(1); + consentSubForm.setPatientId(123); + consentSubForm.setStartDate(Date.from(Instant.parse("2023-04-03T12:00:00Z"))); + consentSubForm.setValue("datum", new Item("datum", Date.from(Instant.parse("2023-04-03T12:00:00Z")))); + consentSubForm.setValue("status", new Item("status", "accepted")); + + var excelForm = new Procedure(this.onkostarApi); + excelForm.setId(111); + excelForm.setPatientId(123); + excelForm.setValue("refdnpmklinikanamnese", new Item("refdnpmklinikanamnese", 2)); + excelForm.addSubProcedure("ufdnpmconsent", consentSubForm); + + var dnpmKlinikAnamneseForm = new Procedure(this.onkostarApi); + dnpmKlinikAnamneseForm.setId(2); + dnpmKlinikAnamneseForm.setPatientId(123); + + when(onkostarApi.getProcedure(anyInt())).thenReturn(dnpmKlinikAnamneseForm); + + this.service.applyConsent(excelForm); + + var argumentCaptor = ArgumentCaptor.forClass(Procedure.class); + verify(onkostarApi, times(1)).saveProcedure(argumentCaptor.capture(), anyBoolean()); + + var savedForm = argumentCaptor.getValue(); + assertThat(savedForm).isExactlyInstanceOf(Procedure.class); + assertThat(savedForm.getValue("ConsentStatusEinwilligungDNPM").getString()).isEqualTo("accepted"); + assertThat(savedForm.getValue("ConsentDatumEinwilligungDNPM").getDate()).isEqualTo("2023-04-03T12:00:00Z"); + } + +} diff --git a/src/test/java/dev/dnpm/services/molekulargenetik/OsMolekluargenetikFormServiceTest.java b/src/test/java/dev/dnpm/services/molekulargenetik/OsMolekluargenetikFormServiceTest.java new file mode 100644 index 0000000..5f2b30d --- /dev/null +++ b/src/test/java/dev/dnpm/services/molekulargenetik/OsMolekluargenetikFormServiceTest.java @@ -0,0 +1,49 @@ +package dev.dnpm.services.molekulargenetik; + +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OsMolekluargenetikFormServiceTest { + + private OsMolekulargenetikFormService service; + + @BeforeEach + void setup() { + this.service = new OsMolekulargenetikFormService(); + } + + @Test + void testShouldReturnVariants() { + + var procedure = new Procedure(null); + procedure.setId(123); + procedure.setFormName("OS.Molekulargenetik"); + + var subProcedure1 = new Procedure(null); + subProcedure1.setId(1123); + subProcedure1.setFormName("OS.Molekulargenetische Untersuchung"); + subProcedure1.setValue("Ergebnis", new Item("Ergebnis", "P")); + subProcedure1.setValue("Untersucht", new Item("Untersucht", "BRAF")); + subProcedure1.setValue("ExonInt", new Item("ExonInt", 123)); + subProcedure1.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + procedure.addSubProcedure("MolekulargenetischeUntersuchung", subProcedure1); + + var subProcedure2 = new Procedure(null); + subProcedure2.setId(2123); + subProcedure2.setFormName("OS.Molekulargenetische Untersuchung"); + subProcedure2.setValue("Ergebnis", new Item("Ergebnis", "CNV")); + subProcedure2.setValue("Untersucht", new Item("Untersucht", "BRAF")); + subProcedure2.setValue("ExonInt", new Item("ExonInt", 123)); + subProcedure2.setValue("Pathogenitaetsklasse", new Item("Pathogenitaetsklasse", "2")); + procedure.addSubProcedure("MolekulargenetischeUntersuchung", subProcedure2); + + var actual = service.getVariants(procedure); + + assertThat(actual).hasSize(2); + } + +} diff --git a/src/test/java/dev/dnpm/services/mtb/DefaultMtbServiceTest.java b/src/test/java/dev/dnpm/services/mtb/DefaultMtbServiceTest.java new file mode 100644 index 0000000..0919d89 --- /dev/null +++ b/src/test/java/dev/dnpm/services/mtb/DefaultMtbServiceTest.java @@ -0,0 +1,185 @@ +package dev.dnpm.services.mtb; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class DefaultMtbServiceTest { + + private IOnkostarApi onkostarApi; + + private DefaultMtbService service; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.service = new DefaultMtbService(onkostarApi); + } + + private static Set<Map.Entry<String, Class<? extends ProcedureToProtocolMapper>>> expectedMappings() { + return Map.ofEntries( + Map.entry("OS.Tumorkonferenz", OsTumorkonferenzToProtocolMapper.class), + Map.entry("OS.Tumorkonferenz.VarianteUKW", OsTumorkonferenzVarianteUkwToProtocolMapper.class), + Map.entry("MR.MTB_Anmeldung", MrMtbAnmeldungToProtocolMapper.class) + ).entrySet(); + } + + @ParameterizedTest + @MethodSource("expectedMappings") + void testShouldMapFormNameToMapper(Map.Entry<String, Class<?>> expectedMapping) { + var procedure = new Procedure(onkostarApi); + procedure.setFormName(expectedMapping.getKey()); + + var actual = service.procedureToProtocolMapper(procedure); + + assertThat(actual).isExactlyInstanceOf(expectedMapping.getValue()); + } + + @Test + void testShouldReturnMtbProtocolForDefaultImplementation() { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Tumorkonferenz"); + procedure1.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure1.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure1.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + var procedures = List.of( + procedure1 + ); + + var actual = service.getProtocol(procedures); + + assertThat(actual).isEqualTo("Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!"); + } + + @Test + void testShouldReturnMtbProtocolForMultipleTK() { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Tumorkonferenz"); + procedure1.setStartDate(Date.from(Instant.parse("2023-02-01T00:00:00Z"))); + procedure1.setValue("Fragestellung", new Item("Fragestellung", "Test immer noch ok?")); + procedure1.setValue("Empfehlung", new Item("Empfehlung", "Do not rerun Test if ok!")); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setFormName("OS.Tumorkonferenz"); + procedure2.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure2.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure2.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + var procedures = List.of( + procedure1, + procedure2 + ); + + var actual = service.getProtocol(procedures); + + assertThat(actual).isEqualTo( + "Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!\n\n" + + "Fragestellung:\nTest immer noch ok?\n\nEmpfehlung:\nDo not rerun Test if ok!" + ); + } + + @Test + void testShouldReturnMtbProtocolForMultipleTKVarianteUKW() { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure1.setStartDate(Date.from(Instant.parse("2023-02-01T00:00:00Z"))); + procedure1.setValue("Fragestellung", new Item("Fragestellung", "Test immer noch ok?")); + procedure1.setValue("Empfehlung", new Item("Empfehlung", "Do not rerun Test if ok!")); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure2.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure2.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure2.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + + var procedures = Arrays.asList( + procedure1, + procedure2 + ); + + var actual = service.getProtocol(procedures); + + assertThat(actual).isEqualTo( + "Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!\n\n" + + "Fragestellung:\nTest immer noch ok?\n\nEmpfehlung:\nDo not rerun Test if ok!" + ); + } + + @Test + void testShouldReturnDistinctProtocolEntries() { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure1.setStartDate(Date.from(Instant.parse("2023-02-01T00:00:00Z"))); + procedure1.setValue("Fragestellung", new Item("Fragestellung", "Test immer noch ok?")); + procedure1.setValue("Empfehlung", new Item("Empfehlung", "Do not rerun Test if ok!")); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure2.setStartDate(Date.from(Instant.parse("2023-02-01T00:00:00Z"))); + procedure2.setValue("Fragestellung", new Item("Fragestellung", "Test immer noch ok?")); + procedure2.setValue("Empfehlung", new Item("Empfehlung", "Do not rerun Test if ok!")); + + var procedure3 = new Procedure(onkostarApi); + procedure3.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure3.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure3.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure3.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + + var procedures = Arrays.asList( + procedure1, + procedure2, + procedure3 + ); + + var actual = service.getProtocol(procedures); + + assertThat(actual).isEqualTo( + "Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!\n\n" + + "Fragestellung:\nTest immer noch ok?\n\nEmpfehlung:\nDo not rerun Test if ok!" + ); + } + + @Test + void testShouldReturnEmptyMtbProtocolForUnknownForm() { + var procedure1 = new Procedure(onkostarApi); + procedure1.setFormName("OS.Tumorkonferenz.Unbekannt"); + procedure1.setStartDate(Date.from(Instant.parse("2023-02-01T00:00:00Z"))); + procedure1.setValue("Fragestellung", new Item("Fragestellung", "Test immer noch ok?")); + procedure1.setValue("Empfehlung", new Item("Empfehlung", "Do not rerun Test if ok!")); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setFormName("OS.Tumorkonferenz.Unbekannt"); + procedure2.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure2.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure2.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + + var procedures = Arrays.asList( + procedure1, + procedure2 + ); + + var actual = service.getProtocol(procedures); + + assertThat(actual).isEmpty(); + } + +} diff --git a/src/test/java/dev/dnpm/services/mtb/MrMtbAnmeldungToProtocolMapperTest.java b/src/test/java/dev/dnpm/services/mtb/MrMtbAnmeldungToProtocolMapperTest.java new file mode 100644 index 0000000..5253cfc --- /dev/null +++ b/src/test/java/dev/dnpm/services/mtb/MrMtbAnmeldungToProtocolMapperTest.java @@ -0,0 +1,139 @@ +package dev.dnpm.services.mtb; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; + +@ExtendWith(MockitoExtension.class) +class MrMtbAnmeldungToProtocolMapperTest { + + private IOnkostarApi onkostarApi; + + private MrMtbAnmeldungToProtocolMapper mapper; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.mapper = new MrMtbAnmeldungToProtocolMapper(onkostarApi); + } + + @Test + void testShouldMapCompletedForm() { + var anmeldung = new Procedure(onkostarApi); + anmeldung.setId(1); + anmeldung.setFormName("MR.MTB_Anmeldung"); + anmeldung.setValue("Fragestellung", new Item("Fragestellung", "Frage?")); + anmeldung.setValue("Empfehlung", new Item("Empfehlung", 2)); + + var empfehlung = new Procedure(onkostarApi); + empfehlung.setId(2); + empfehlung.setFormName("MR.MTB_Empfehlung"); + + var einzelempfehlung1 = new Procedure(onkostarApi); + einzelempfehlung1.setId(10); + einzelempfehlung1.setFormName("MR.MTB_Einzelempfehlung"); + einzelempfehlung1.setValue("Prioritaet", new Item("Empfehlungsprio", 1)); + einzelempfehlung1.setValue("Empfehlung", new Item("Empfehlung", "Empfehlung1")); + + var einzelempfehlung2 = new Procedure(onkostarApi); + einzelempfehlung2.setId(20); + einzelempfehlung2.setFormName("MR.MTB_Einzelempfehlung"); + einzelempfehlung2.setValue("Prioritaet", new Item("Empfehlungsprio", 2)); + einzelempfehlung2.setValue("Empfehlung", new Item("Empfehlung", "Empfehlung2")); + + doAnswer(invocationOnMock -> { + var procedureId = invocationOnMock.getArgument(0, Integer.class); + if (2 == procedureId) { + return empfehlung; + } else if (10 == procedureId) { + return einzelempfehlung1; + } else if (20 == procedureId) { + return einzelempfehlung2; + } + return null; + }).when(onkostarApi).getProcedure(anyInt()); + + doAnswer(invocationOnMock -> { + var procedureId = invocationOnMock.getArgument(0, Integer.class); + if (2 == procedureId) { + return Set.of(einzelempfehlung1, einzelempfehlung2); + } + return null; + }).when(onkostarApi).getSubprocedures(anyInt()); + + var actual = this.mapper.apply(anmeldung); + + assertThat(actual) + .isPresent() + .contains( + "Fragestellung:\nFrage?\n\n" + + "Empfehlung:\nEmpfehlung1\n\n" + + "Empfehlung:\nEmpfehlung2" + ); + } + + @Test + void testShouldMapFormWithMissingEinzelempfehlungen() { + var anmeldung = new Procedure(onkostarApi); + anmeldung.setId(1); + anmeldung.setFormName("MR.MTB_Anmeldung"); + anmeldung.setValue("Fragestellung", new Item("Fragestellung", "Frage?")); + anmeldung.setValue("Empfehlung", new Item("Empfehlung", 2)); + + var empfehlung = new Procedure(onkostarApi); + empfehlung.setId(2); + empfehlung.setFormName("MR.MTB_Empfehlung"); + + doAnswer(invocationOnMock -> { + var procedureId = invocationOnMock.getArgument(0, Integer.class); + if (2 == procedureId) { + return empfehlung; + } + return null; + }).when(onkostarApi).getProcedure(anyInt()); + + var actual = this.mapper.apply(anmeldung); + + assertThat(actual) + .isPresent() + .contains("Fragestellung:\nFrage?"); + } + + @Test + void testShouldMapFormWithMissingEmpfehlung() { + var anmeldung = new Procedure(onkostarApi); + anmeldung.setId(1); + anmeldung.setFormName("MR.MTB_Anmeldung"); + anmeldung.setValue("Fragestellung", new Item("Fragestellung", "Frage?")); + + var actual = this.mapper.apply(anmeldung); + + assertThat(actual) + .isPresent() + .contains("Fragestellung:\nFrage?"); + } + + @Test + void testShouldMapFormWithMissingFragestellungAndEmpfehlung() { + var anmeldung = new Procedure(onkostarApi); + anmeldung.setId(1); + anmeldung.setFormName("MR.MTB_Anmeldung"); + + var actual = this.mapper.apply(anmeldung); + + assertThat(actual).isEmpty(); + } +} diff --git a/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzToProtocolMapperTest.java b/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzToProtocolMapperTest.java new file mode 100644 index 0000000..863ed55 --- /dev/null +++ b/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzToProtocolMapperTest.java @@ -0,0 +1,47 @@ +package dev.dnpm.services.mtb; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class OsTumorkonferenzToProtocolMapperTest { + + private IOnkostarApi onkostarApi; + + private OsTumorkonferenzToProtocolMapper mapper; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.mapper = new OsTumorkonferenzToProtocolMapper(); + } + + @Test + void testShouldReturnMtbProtocolForDefaultImplementation() { + var procedure = new Procedure(onkostarApi); + procedure.setFormName("OS.Tumorkonferenz"); + procedure.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + var actual = mapper.apply(procedure); + + assertThat(actual) + .isPresent() + .contains("Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!"); + } + +} diff --git a/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzVarianteUkwToProtocolMapperTest.java b/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzVarianteUkwToProtocolMapperTest.java new file mode 100644 index 0000000..0768a2f --- /dev/null +++ b/src/test/java/dev/dnpm/services/mtb/OsTumorkonferenzVarianteUkwToProtocolMapperTest.java @@ -0,0 +1,47 @@ +package dev.dnpm.services.mtb; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class OsTumorkonferenzVarianteUkwToProtocolMapperTest { + + private IOnkostarApi onkostarApi; + + private OsTumorkonferenzVarianteUkwToProtocolMapper mapper; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.mapper = new OsTumorkonferenzVarianteUkwToProtocolMapper(); + } + + @Test + void testShouldReturnMtbProtocolForDefaultImplementation() { + var procedure = new Procedure(onkostarApi); + procedure.setFormName("OS.Tumorkonferenz.VarianteUKW"); + procedure.setStartDate(Date.from(Instant.parse("2023-01-01T00:00:00Z"))); + procedure.setValue("Fragestellung", new Item("Fragestellung", "Test ok?")); + procedure.setValue("Empfehlung", new Item("Empfehlung", "Rerun Test if not ok!")); + + var actual = mapper.apply(procedure); + + assertThat(actual) + .isPresent() + .contains("Fragestellung:\nTest ok?\n\nEmpfehlung:\nRerun Test if not ok!"); + } + +} diff --git a/src/test/java/dev/dnpm/services/strahlentherapie/DefaultStrahlentherapieServiceTest.java b/src/test/java/dev/dnpm/services/strahlentherapie/DefaultStrahlentherapieServiceTest.java new file mode 100644 index 0000000..9aaa68b --- /dev/null +++ b/src/test/java/dev/dnpm/services/strahlentherapie/DefaultStrahlentherapieServiceTest.java @@ -0,0 +1,104 @@ +package dev.dnpm.services.strahlentherapie; + +import dev.dnpm.services.SettingsService; +import de.itc.onkostar.api.*; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class DefaultStrahlentherapieServiceTest { + + private IOnkostarApi onkostarApi; + + private SettingsService settingsService; + + private DefaultStrahlentherapieService service; + + @BeforeEach + void setup(@Mock IOnkostarApi onkostarApi, @Mock SettingsService settingsService) { + this.onkostarApi = onkostarApi; + this.settingsService = settingsService; + this.service = new DefaultStrahlentherapieService(onkostarApi, settingsService); + } + + @Test + void testShouldRequestProceduresWithDefaultFormName() { + when(this.settingsService.getSetting(anyString())).thenReturn(Optional.empty()); + + doAnswer(invocationOnMock -> { + var procedure = new Procedure(onkostarApi); + procedure.setId(1); + procedure.setFormName("OS.Strahlentherapie"); + procedure.setStartDate(Date.from(Instant.parse("2023-07-01T06:00:00Z"))); + procedure.setEditState(ProcedureEditStateType.COMPLETED); + procedure.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + return Lists.list(procedure); + }).when(this.onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + doAnswer(invocationOnMock -> { + var disease = new Disease(onkostarApi); + disease.setId(1); + disease.setPatientId(123); + return Lists.list(disease); + }).when(this.onkostarApi).getDiseasesByPatientId(anyInt()); + + var patient = new Patient(onkostarApi); + patient.setId(123); + + service.ecogStatus(patient); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(onkostarApi, times(1)).getProceduresForDiseaseByForm(anyInt(), argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).isEqualTo("OS.Strahlentherapie"); + } + + @Test + void testShouldReturnListOfEcogStatusWithDate() { + doAnswer(invocationOnMock -> { + var disease = new Disease(onkostarApi); + disease.setId(1); + return List.of(disease); + }).when(this.onkostarApi).getDiseasesByPatientId(anyInt()); + + doAnswer(invocationOnMock -> { + var procedure1 = new Procedure(onkostarApi); + procedure1.setId(1); + procedure1.setFormName("OS.Strahlentherapie"); + procedure1.setStartDate(Date.from(Instant.parse("2023-07-01T06:00:00Z"))); + procedure1.setEditState(ProcedureEditStateType.COMPLETED); + procedure1.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setId(2); + procedure2.setFormName("OS.Strahlentherapie"); + procedure2.setStartDate(Date.from(Instant.parse("2023-07-12T06:00:00Z"))); + procedure2.setEditState(ProcedureEditStateType.COMPLETED); + procedure2.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 2)); + return List.of(procedure1, procedure2); + }).when(this.onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var actual = service.ecogStatus(patient); + + assertThat(actual) + .isNotNull() + .isExactlyInstanceOf(ArrayList.class) + .hasSize(2); + } +} diff --git a/src/test/java/dev/dnpm/services/systemtherapie/DefaultSystemtherapieServiceTest.java b/src/test/java/dev/dnpm/services/systemtherapie/DefaultSystemtherapieServiceTest.java new file mode 100644 index 0000000..2744c52 --- /dev/null +++ b/src/test/java/dev/dnpm/services/systemtherapie/DefaultSystemtherapieServiceTest.java @@ -0,0 +1,131 @@ +package dev.dnpm.services.systemtherapie; + +import dev.dnpm.services.SettingsService; +import de.itc.onkostar.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class DefaultSystemtherapieServiceTest { + + private IOnkostarApi onkostarApi; + + private SettingsService settingsService; + + private DefaultSystemtherapieService service; + + @BeforeEach + void setup(@Mock IOnkostarApi onkostarApi, @Mock SettingsService settingsService) { + this.onkostarApi = onkostarApi; + this.settingsService = settingsService; + this.service = new DefaultSystemtherapieService(onkostarApi, settingsService); + } + + private static Set<Map.Entry<String, Class<OsSystemischeTherapieToProzedurwerteMapper>>> expectedMapperMappings() { + return Map.ofEntries(Map.entry("OS.Systemische Therapie", OsSystemischeTherapieToProzedurwerteMapper.class), Map.entry("OS.Systemische Therapie.VarianteUKW", OsSystemischeTherapieToProzedurwerteMapper.class)).entrySet(); + } + + @ParameterizedTest + @MethodSource("expectedMapperMappings") + void testShouldMapFormNameToMapper(Map.Entry<String, Class<?>> expectedMapping) { + var procedure = new Procedure(onkostarApi); + procedure.setFormName(expectedMapping.getKey()); + + var actual = service.prozedurToProzedurwerteMapper(procedure); + + assertThat(actual).isExactlyInstanceOf(expectedMapping.getValue()); + } + + private static List<String> formnameSetting() { + return List.of("OS.Systemische Therapie", "OS.Systemische Therapie.VarianteUKW"); + } + + @ParameterizedTest + @MethodSource("formnameSetting") + void testShouldRequestProceduresWithExpectedFormName(String expectedFormName) { + when(this.settingsService.getSetting(anyString())).thenReturn(Optional.of(expectedFormName)); + when(this.onkostarApi.getProceduresForDiseaseByForm(anyInt(), anyString())).thenReturn(List.of()); + + service.getSystemischeTherapienFromDiagnose(123); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(onkostarApi, times(1)).getProceduresForDiseaseByForm(anyInt(), argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).isEqualTo(expectedFormName); + } + + @Test + void testShouldRequestProceduresWithDefaultFormName() { + when(this.settingsService.getSetting(anyString())).thenReturn(Optional.empty()); + when(this.onkostarApi.getProceduresForDiseaseByForm(anyInt(), anyString())).thenReturn(List.of()); + + service.getSystemischeTherapienFromDiagnose(123); + + var argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(onkostarApi, times(1)).getProceduresForDiseaseByForm(anyInt(), argumentCaptor.capture()); + assertThat(argumentCaptor.getValue()).isEqualTo("OS.Systemische Therapie"); + } + + @Test + void testShouldReturnSystemischeTherapienFromDiagnose() { + doAnswer(invocationOnMock -> { + var procedure = new Procedure(onkostarApi); + procedure.setFormName("OS.Systemische Therapie"); + return List.of(procedure); + }).when(this.onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + var actual = service.getSystemischeTherapienFromDiagnose(1); + + assertThat(actual) + .isNotNull() + .isExactlyInstanceOf(ArrayList.class) + .hasSize(1); + } + + @Test + void testShouldReturnListOfEcogStatusWithDate() { + doAnswer(invocationOnMock -> { + var disease = new Disease(onkostarApi); + disease.setId(1); + return List.of(disease); + }).when(this.onkostarApi).getDiseasesByPatientId(anyInt()); + + doAnswer(invocationOnMock -> { + var procedure1 = new Procedure(onkostarApi); + procedure1.setId(1); + procedure1.setFormName("OS.Systemische Therapie"); + procedure1.setStartDate(Date.from(Instant.parse("2023-07-01T06:00:00Z"))); + procedure1.setEditState(ProcedureEditStateType.COMPLETED); + procedure1.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 1)); + + var procedure2 = new Procedure(onkostarApi); + procedure2.setId(2); + procedure2.setFormName("OS.Systemische Therapie"); + procedure2.setStartDate(Date.from(Instant.parse("2023-07-12T06:00:00Z"))); + procedure2.setEditState(ProcedureEditStateType.COMPLETED); + procedure2.setValue("ECOGvorTherapie", new Item("ECOGvorTherapie", 2)); + return List.of(procedure1, procedure2); + }).when(this.onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + var patient = new Patient(onkostarApi); + patient.setId(1); + + var actual = service.ecogStatus(patient); + + assertThat(actual) + .isNotNull() + .isExactlyInstanceOf(ArrayList.class) + .hasSize(2); + } +} diff --git a/src/test/java/dev/dnpm/services/systemtherapie/ProzedurToProzedurwerteMapperTest.java b/src/test/java/dev/dnpm/services/systemtherapie/ProzedurToProzedurwerteMapperTest.java new file mode 100644 index 0000000..6dbdada --- /dev/null +++ b/src/test/java/dev/dnpm/services/systemtherapie/ProzedurToProzedurwerteMapperTest.java @@ -0,0 +1,71 @@ +package dev.dnpm.services.systemtherapie; + +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Date; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class ProzedurToProzedurwerteMapperTest { + + private IOnkostarApi onkostarApi; + + private OsSystemischeTherapieToProzedurwerteMapper mapper; + + @BeforeEach + void setup( + @Mock IOnkostarApi onkostarApi + ) { + this.onkostarApi = onkostarApi; + this.mapper = new OsSystemischeTherapieToProzedurwerteMapper(); + } + + @Test + void testShouldReturnSystemischeTherapienFromDiagnose() { + var procedure = new Procedure(onkostarApi); + procedure.setFormName("OS.Systemische Therapie"); + procedure.setValue("Beginn", new Item("Beginn", Date.from(Instant.parse("2023-01-01T00:00:00Z")))); + procedure.setValue("Ende", new Item("Ende", Date.from(Instant.parse("2023-01-31T00:00:00Z")))); + procedure.setValue("Beendigung", new Item("Beendigungsstatus", "E")); + procedure.setValue("Ergebnis", new Item("Ergebnis", "T")); + + var substanzen = new ArrayList<>(); + substanzen.add(Map.of( + "Substanz", "Testsubstanz", + "Substanz_shortDescription", "Testsubstanz" + )); + substanzen.add(Map.of( + "Substanz", "L01AA01", + "Substanz_shortDescription", "cyclophosphamide" + )); + procedure.setValue("SubstanzenList", new Item("SubstanzenList", substanzen)); + + var actual = mapper.apply(procedure); + + assertThat(actual).isPresent(); + + assertThat(actual.get()).containsEntry("Beginn", Date.from(Instant.parse("2023-01-01T00:00:00Z")).toString()); + assertThat(actual.get()).containsEntry("Ende", Date.from(Instant.parse("2023-01-31T00:00:00Z")).toString()); + assertThat(actual.get()).containsEntry("Beendigung", "E"); + assertThat(actual.get()).containsEntry("Ergebnis", "T"); + assertThat(actual.get()).containsEntry("Wirkstoffe", "Testsubstanz, cyclophosphamide"); + assertThat(actual.get()).containsEntry("WirkstoffCodes", + "[" + + "{\"system\":\"other\",\"code\":\"Testsubstanz\",\"substance\":\"Testsubstanz\"}," + + "{\"system\":\"ATC\",\"code\":\"L01AA01\",\"substance\":\"cyclophosphamide\"}" + + "]" + ); + } + +} diff --git a/src/test/java/dev/dnpm/services/therapieplan/DefaultTherapieplanServiceTest.java b/src/test/java/dev/dnpm/services/therapieplan/DefaultTherapieplanServiceTest.java new file mode 100644 index 0000000..0dff0ea --- /dev/null +++ b/src/test/java/dev/dnpm/services/therapieplan/DefaultTherapieplanServiceTest.java @@ -0,0 +1,169 @@ +package dev.dnpm.services.therapieplan; + +import dev.dnpm.services.FormService; +import de.itc.onkostar.api.IOnkostarApi; +import de.itc.onkostar.api.Item; +import de.itc.onkostar.api.Procedure; +import de.itc.onkostar.api.constants.JaNeinUnbekannt; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class DefaultTherapieplanServiceTest { + + @Mock + private IOnkostarApi onkostarApi; + + @Mock + private FormService formService; + + private TherapieplanService service; + + @BeforeEach + void setUp() { + this.service = new DefaultTherapieplanService(onkostarApi, formService); + } + + @Test + void shouldNotUpdateSubformsOrSectionsIfMultipleMtbConfiguration() throws Exception { + this.service.updateRequiredMtbEntries(new Procedure(onkostarApi)); + verify(onkostarApi, never()).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void shouldNotUpdateSectionsIfSectionsNotEnabled() throws Exception { + var testProcedure = baseProcedure(onkostarApi); + + // Keine humangenetische Beratung und keine Reevaluation empfohlen + testProcedure.setValue("humangenberatung", new Item("humangen_beratung", JaNeinUnbekannt.NEIN.getCode())); + testProcedure.setValue("reevaluation", new Item("reevaluation", JaNeinUnbekannt.NEIN.getCode())); + + this.service.updateRequiredMtbEntries(testProcedure); + + verify(onkostarApi, never()).saveProcedure(any(Procedure.class), anyBoolean()); + } + + @Test + void shouldUpdateSectionsIfNoReevaluation() throws Exception { + var testProcedure = baseProcedure(onkostarApi); + + // Humangenetische Beratung aber keine Reevaluation + testProcedure.setValue("humangenberatung", new Item("humangen_beratung", JaNeinUnbekannt.JA.getCode())); + testProcedure.setValue("humangenberbegruendung", new Item("humangen_ber_begruendung", "Das ist die Begründung")); + testProcedure.setValue("reevaluation", new Item("reevaluation", JaNeinUnbekannt.NEIN.getCode())); + + this.service.updateRequiredMtbEntries(testProcedure); + + var captor = ArgumentCaptor.forClass(Procedure.class); + verify(onkostarApi, times(1)).saveProcedure(captor.capture(), anyBoolean()); + + var capturedProcedure = captor.getValue(); + + assertThat(capturedProcedure.getValue("reftkreevaluation")).isNull(); + assertThat(capturedProcedure.getValue("datumtkreevaluation")).isNull(); + + assertThat(capturedProcedure.getValue("reftkhumangenber")).isNotNull(); + assertThat(capturedProcedure.getValue("reftkhumangenber").getInt()).isEqualTo(procedureId); + assertThat(capturedProcedure.getValue("datumtkhumangenber")).isNotNull(); + assertThat(capturedProcedure.getValue("datumtkhumangenber").getDate()).isEqualTo(testDate); + } + + @Test + void shouldUpdateSectionsIfNoHumanGenConsultation() throws Exception { + var testProcedure = baseProcedure(onkostarApi); + + // Humangenetische Beratung aber keine Reevaluation + testProcedure.setValue("humangenberatung", new Item("humangen_beratung", JaNeinUnbekannt.NEIN.getCode())); + testProcedure.setValue("reevaluation", new Item("reevaluation", JaNeinUnbekannt.JA.getCode())); + + this.service.updateRequiredMtbEntries(testProcedure); + + var captor = ArgumentCaptor.forClass(Procedure.class); + verify(onkostarApi, times(1)).saveProcedure(captor.capture(), anyBoolean()); + + var capturedProcedure = captor.getValue(); + + assertThat(capturedProcedure.getValue("reftkhumangenber")).isNull(); + assertThat(capturedProcedure.getValue("datumtkhumangenber")).isNull(); + + assertThat(capturedProcedure.getValue("reftkreevaluation")).isNotNull(); + assertThat(capturedProcedure.getValue("reftkreevaluation").getInt()).isEqualTo(procedureId); + assertThat(capturedProcedure.getValue("datumtkreevaluation")).isNotNull(); + assertThat(capturedProcedure.getValue("datumtkreevaluation").getDate()).isEqualTo(testDate); + } + + @Test + void shouldFindFollowUps() { + doAnswer(invocationOnMock -> { + var testProcedure = baseProcedure(onkostarApi); + testProcedure.setId(procedureId); + testProcedure.setFormName("DNPM UF Einzelempfehlung"); + testProcedure.addDiseaseId(123); + return testProcedure; + }).when(onkostarApi).getProcedure(anyInt()); + + doAnswer(invocationOnMock -> { + var diseaseId = invocationOnMock.getArgument(0, Integer.class); + var formName = invocationOnMock.getArgument(1, String.class); + var procedure = baseProcedure(onkostarApi); + procedure.addDiseaseId(diseaseId); + procedure.setFormName(formName); + procedure.setValue("LinkTherapieempfehlung", new Item("LinkTherapieempfehlung", procedureId)); + return List.of(procedure); + }).when(onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + var followUps = this.service.findReferencedFollowUpsForSubform(1); + + assertThat(followUps).hasSize(1) + .allSatisfy(procedure -> assertThat(procedure.getFormName()).isEqualTo("DNPM FollowUp")); + } + + @Test + void shouldFindFollowUpsById() { + var testProcedure = baseProcedure(onkostarApi); + testProcedure.setId(procedureId); + testProcedure.setFormName("DNPM UF Einzelempfehlung"); + testProcedure.addDiseaseId(123); + + doAnswer(invocationOnMock -> { + var diseaseId = invocationOnMock.getArgument(0, Integer.class); + var formName = invocationOnMock.getArgument(1, String.class); + var procedure = baseProcedure(onkostarApi); + procedure.addDiseaseId(diseaseId); + procedure.setFormName(formName); + procedure.setValue("LinkTherapieempfehlung", new Item("LinkTherapieempfehlung", procedureId)); + return List.of(procedure); + }).when(onkostarApi).getProceduresForDiseaseByForm(anyInt(), anyString()); + + var followUps = this.service.findReferencedFollowUpsForSubform(testProcedure); + + assertThat(followUps).hasSize(1) + .allSatisfy(procedure -> assertThat(procedure.getFormName()).isEqualTo("DNPM FollowUp")); + } + + private static final int procedureId = 1234; + private static final Date testDate = Date.from(Instant.parse("2023-03-15T09:43:00Z")); + + private Procedure baseProcedure(final IOnkostarApi onkostarApi) { + var testProcedure = new Procedure(onkostarApi); + testProcedure.setId(1000); + + // Setzen MTB Referenz und Datum MTB + testProcedure.setValue("referstemtb", new Item("ref_tumorkonferenz", procedureId)); + testProcedure.setValue("datum", new Item("datum", testDate)); + + return testProcedure; + } + +} diff --git a/src/test/java/dev/dnpm/services/therapieplan/TherapieplanServiceFactoryTest.java b/src/test/java/dev/dnpm/services/therapieplan/TherapieplanServiceFactoryTest.java new file mode 100644 index 0000000..e8d3600 --- /dev/null +++ b/src/test/java/dev/dnpm/services/therapieplan/TherapieplanServiceFactoryTest.java @@ -0,0 +1,51 @@ +package dev.dnpm.services.therapieplan; + +import dev.dnpm.services.FormService; +import dev.dnpm.services.SettingsService; +import de.itc.onkostar.api.IOnkostarApi; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TherapieplanServiceFactoryTest { + + @Mock + private IOnkostarApi onkostarApi; + + @Mock + private FormService formService; + + @Mock + private SettingsService settingsService; + + private TherapieplanServiceFactory therapieplanServiceFactory; + + @BeforeEach + void setup() { + this.therapieplanServiceFactory = new TherapieplanServiceFactory(onkostarApi, settingsService, formService); + } + + @Test + void testShouldReturnDefaultTherapieplanServiceIfSettingIsFalse() { + when(settingsService.multipleMtbsInMtbEpisode()).thenReturn(false); + + var actual = this.therapieplanServiceFactory.currentUsableInstance(); + + assertThat(actual).isInstanceOf(DefaultTherapieplanService.class); + } + + @Test + void testShouldReturnMultipleMtbTherapieplanServiceIfSettingIsTrue() { + when(settingsService.multipleMtbsInMtbEpisode()).thenReturn(true); + + var actual = this.therapieplanServiceFactory.currentUsableInstance(); + + assertThat(actual).isInstanceOf(MultipleMtbTherapieplanService.class); + } +} |
