From 072305497e0814b75af7e34d248fcd12b447c5a3 Mon Sep 17 00:00:00 2001 From: cbioportal import user Date: Thu, 26 Dec 2024 20:52:31 -0500 Subject: [PATCH] very wip - adding tests --- docker/web-and-data/Dockerfile | 2 +- .../org/cbioportal/PortalApplication.java | 6 +- ...SourceConfig.java => FederatorConfig.java} | 2 +- .../impl/FederatedViewServiceImpl.java | 55 +++- ...ources.properties => federator.properties} | 4 +- .../service/impl/BaseServiceImplTest.java | 1 + .../impl/FederatedViewServiceImplTest.java | 182 ++++++++++++++ .../FederatedApiIntegrationTest.java | 46 ++++ .../web/FederatedViewControllerTest.java | 234 ++++++++++++++++++ .../org/cbioportal/web/config/TestConfig.java | 13 + 10 files changed, 530 insertions(+), 15 deletions(-) rename src/main/java/org/cbioportal/persistence/fedapi/{FederatedDataSourceConfig.java => FederatorConfig.java} (93%) rename src/main/resources/{fed-sources.properties => federator.properties} (54%) create mode 100644 src/test/java/org/cbioportal/service/impl/FederatedViewServiceImplTest.java create mode 100644 src/test/java/org/cbioportal/test/integration/FederatedApiIntegrationTest.java create mode 100644 src/test/java/org/cbioportal/web/FederatedViewControllerTest.java diff --git a/docker/web-and-data/Dockerfile b/docker/web-and-data/Dockerfile index 5abdafb9668..1cc7b3f5840 100644 --- a/docker/web-and-data/Dockerfile +++ b/docker/web-and-data/Dockerfile @@ -23,7 +23,7 @@ WORKDIR /cbioportal RUN mvn dependency:go-offline --fail-never COPY $PWD /cbioportal -RUN mvn install package -DskipTests -q +RUN mvn install package -DskipTests -Dfed.mode=FEDERATOR -q RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*-exec.jar) FROM eclipse-temurin:21 diff --git a/src/main/java/org/cbioportal/PortalApplication.java b/src/main/java/org/cbioportal/PortalApplication.java index 3d60501a3af..df3c40efcb4 100644 --- a/src/main/java/org/cbioportal/PortalApplication.java +++ b/src/main/java/org/cbioportal/PortalApplication.java @@ -1,6 +1,6 @@ package org.cbioportal; -import org.cbioportal.persistence.fedapi.FederatedDataSourceConfig; +import org.cbioportal.persistence.fedapi.FederatorConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; @@ -19,9 +19,9 @@ @PropertySource(ignoreResourceNotFound = true, value = "classpath:maven.properties"), @PropertySource(ignoreResourceNotFound = true, value = "classpath:git.properties"), @PropertySource(ignoreResourceNotFound = true, value = "classpath:springdoc.properties"), - @PropertySource(ignoreResourceNotFound = true, value = "classpath:fed-sources.properties") + @PropertySource(ignoreResourceNotFound = true, value = "classpath:federator.properties") }) -@EnableConfigurationProperties(FederatedDataSourceConfig.class) +@EnableConfigurationProperties(FederatorConfig.class) public class PortalApplication { public static void main(String[] args) { SpringApplication.run(PortalApplication.class, args); diff --git a/src/main/java/org/cbioportal/persistence/fedapi/FederatedDataSourceConfig.java b/src/main/java/org/cbioportal/persistence/fedapi/FederatorConfig.java similarity index 93% rename from src/main/java/org/cbioportal/persistence/fedapi/FederatedDataSourceConfig.java rename to src/main/java/org/cbioportal/persistence/fedapi/FederatorConfig.java index 82c166c2276..97b935d97f0 100644 --- a/src/main/java/org/cbioportal/persistence/fedapi/FederatedDataSourceConfig.java +++ b/src/main/java/org/cbioportal/persistence/fedapi/FederatorConfig.java @@ -8,7 +8,7 @@ @Configuration @ConfigurationProperties(prefix = "fed") -public class FederatedDataSourceConfig { +public class FederatorConfig { private List sources = new ArrayList<>(); diff --git a/src/main/java/org/cbioportal/service/impl/FederatedViewServiceImpl.java b/src/main/java/org/cbioportal/service/impl/FederatedViewServiceImpl.java index cdeffdd2b56..205243d0e74 100644 --- a/src/main/java/org/cbioportal/service/impl/FederatedViewServiceImpl.java +++ b/src/main/java/org/cbioportal/service/impl/FederatedViewServiceImpl.java @@ -5,7 +5,7 @@ import org.cbioportal.model.ClinicalDataCountItem; import org.cbioportal.persistence.fedapi.FederatedDataSource; import org.cbioportal.persistence.fedapi.FederatedDataSourceImpl; -import org.cbioportal.persistence.fedapi.FederatedDataSourceConfig; +import org.cbioportal.persistence.fedapi.FederatorConfig; import org.cbioportal.service.ClinicalAttributeService; import org.cbioportal.service.ClinicalDataService; import org.cbioportal.service.FederatedViewService; @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import java.util.stream.Collectors; enum FederationMode { @@ -39,7 +41,7 @@ public class FederatedViewServiceImpl implements FederatedViewService { private List dataSourceStudies; @Autowired - private FederatedDataSourceConfig federatedDataSourceConfig; + private FederatorConfig federatorConfig; @Autowired private ClinicalDataService clinicalDataService; @@ -60,8 +62,9 @@ public class FederatedViewServiceImpl implements FederatedViewService { public List fetchClinicalAttributes() throws FederationException { if (federationMode == FederationMode.FEDERATOR) { try { - FederatedDataSource federatedDataSource = new FederatedDataSourceImpl(federatedDataSourceConfig.getSources().get(0)); - return federatedDataSource.fetchClinicalAttributes().get(); + return aggResultsFromDifferentSources( + s -> s.fetchClinicalAttributes() + ); } catch (Exception e) { throw new FederationException("Failed to fetch clinical attributes", e); } @@ -72,19 +75,53 @@ public List fetchClinicalAttributes() throws FederationExcept } } + private List aggResultsFromDifferentSources( + Function>> apiFunc + ) throws Exception { + // Each list = results from one data source + // WhenAll's over the list of tasks to get a CF>> + // Awaits this to get a List> + // Once we have the list of lists... for now just flatten to merge them (assume each source has unique studies) + + List sources = federatorConfig.getSources() + .stream() + .map(inf -> new FederatedDataSourceImpl(inf)) + .toList(); + + List>> futures = sources.stream() + .map(apiFunc::apply) + .toList(); + + CompletableFuture>> combinedFuture = + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .thenApply(v -> + futures.stream() + .map(CompletableFuture::join) // Join each future result + .collect(Collectors.toList()) // Collect into List> + ); + + List> results = combinedFuture.get(); + List flattened = results.stream() + .flatMap(List::stream) // Flatten each sublist + .collect(Collectors.toList()); + return flattened; + } + @Override public List fetchClinicalDataCounts( ClinicalDataCountFilter filter ) throws FederationException { if (federationMode == FederationMode.FEDERATOR) { try { - FederatedDataSource federatedDataSource = new FederatedDataSourceImpl(federatedDataSourceConfig.getSources().get(0)); - return federatedDataSource.fetchClinicalDataCounts(filter).get(); + return aggResultsFromDifferentSources( + s -> s.fetchClinicalDataCounts(filter) + ); } catch (Exception e) { throw new FederationException("Failed to fetch clinical data counts", e); } } else if (federationMode == FederationMode.DATASOURCE) { // TODO: replicate the logic for cacheableClinicalDataCounts here + filter.getStudyViewFilter().setStudyIds(dataSourceStudies); return cachedClinicalDataCounts(filter); } else { throw new FederationException("Federation is disabled"); @@ -118,13 +155,15 @@ public List fetchClinicalDataBinCounts( ) throws FederationException { if (federationMode == FederationMode.FEDERATOR) { try { - FederatedDataSource federatedDataSource = new FederatedDataSourceImpl(federatedDataSourceConfig.getSources().get(0)); - return federatedDataSource.fetchClinicalDataBinCounts(filter).get(); + return aggResultsFromDifferentSources( + s -> s.fetchClinicalDataBinCounts(filter) + ); } catch (Exception e) { throw new FederationException("Failed to fetch clinical data bin counts", e); } } else if (federationMode == FederationMode.DATASOURCE) { // TODO: replicate the logic for cacheableClinicalDataBinCounts here + filter.getStudyViewFilter().setStudyIds(dataSourceStudies); return cachedFetchClinicalDataBinCounts(filter); } else { throw new FederationException("Federation is disabled"); diff --git a/src/main/resources/fed-sources.properties b/src/main/resources/federator.properties similarity index 54% rename from src/main/resources/fed-sources.properties rename to src/main/resources/federator.properties index ccb67af07a0..88bae8c2263 100644 --- a/src/main/resources/fed-sources.properties +++ b/src/main/resources/federator.properties @@ -1,5 +1,5 @@ fed.sources[0].name=Test cBioPortal 1 fed.sources[0].base-url=https://test.cbioportal.dev.aws.mskcc.org/api-fed -fed.sources[0].name=Test cBioPortal 2 -fed.sources[0].base-url=https://test2.cbioportal.dev.aws.mskcc.org/api-fed \ No newline at end of file +fed.sources[1].name=Test cBioPortal 2 +fed.sources[1].base-url=https://test2.cbioportal.dev.aws.mskcc.org/api-fed \ No newline at end of file diff --git a/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java b/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java index 827a7b752a5..ad9bc77df67 100644 --- a/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java +++ b/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java @@ -8,6 +8,7 @@ public class BaseServiceImplTest { public static final String SORT = "sort"; public static final String DIRECTION = "direction"; public static final String STUDY_ID = "study_id"; + public static final String STUDY_ID_2 = "study_id_2"; public static final String MOLECULAR_PROFILE_ID = "molecular_profile_id"; public static final String MOLECULAR_PROFILE_ID_A = "molecular_profile_id_a"; public static final String MOLECULAR_PROFILE_ID_B = "molecular_profile_id_b"; diff --git a/src/test/java/org/cbioportal/service/impl/FederatedViewServiceImplTest.java b/src/test/java/org/cbioportal/service/impl/FederatedViewServiceImplTest.java new file mode 100644 index 00000000000..0b3a8b6c9aa --- /dev/null +++ b/src/test/java/org/cbioportal/service/impl/FederatedViewServiceImplTest.java @@ -0,0 +1,182 @@ +package org.cbioportal.service.impl; + +import org.cbioportal.model.ClinicalAttribute; +import org.cbioportal.model.Sample; +import org.cbioportal.persistence.ClinicalAttributeRepository; +import org.cbioportal.persistence.ClinicalDataRepository; +import org.cbioportal.persistence.SampleRepository; +import org.cbioportal.service.ClinicalAttributeService; +import org.cbioportal.service.ClinicalDataService; +import org.cbioportal.service.exception.FederationException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class FederatedViewServiceImplTest extends BaseServiceImplTest { + + @InjectMocks + private FederatedViewServiceImpl federatedViewService; + + @Mock + private List dataSourceStudies = List.of( + STUDY_ID, + STUDY_ID_2 + ); + + @Mock + private ClinicalAttributeService clinicalAttributeService; + + @Mock + private ClinicalDataService clinicalDataService; + + + private List mockClinicalAttributes() { + + var attrib11 = new ClinicalAttribute(); + attrib11.setDisplayName("Sex"); + attrib11.setDescription("Sex"); + attrib11.setDatatype("STRING"); + attrib11.setPatientAttribute(false); + attrib11.setPriority("1"); + attrib11.setAttrId("SEX"); + attrib11.setCancerStudyIdentifier(STUDY_ID); + + var attrib21 = new ClinicalAttribute(); + attrib21.setDisplayName("Age"); + attrib21.setDescription("Age"); + attrib21.setDatatype("NUMBER"); + attrib21.setPatientAttribute(false); + attrib21.setPriority("1"); + attrib21.setAttrId("AGE"); + attrib21.setCancerStudyIdentifier(STUDY_ID); + + var attrib12 = new ClinicalAttribute(); + attrib12.setDisplayName("Sex"); + attrib12.setDescription("Sex"); + attrib12.setDatatype("STRING"); + attrib12.setPatientAttribute(false); + attrib12.setPriority("1"); + attrib12.setAttrId("SEX"); + attrib12.setCancerStudyIdentifier(STUDY_ID_2); + + var attrib22 = new ClinicalAttribute(); + attrib22.setDisplayName("Age"); + attrib22.setDescription("Age"); + attrib22.setDatatype("NUMBER"); + attrib22.setPatientAttribute(false); + attrib22.setPriority("1"); + attrib22.setAttrId("AGE"); + attrib22.setCancerStudyIdentifier(STUDY_ID_2); + + return List.of(attrib11, attrib21, attrib12, attrib22); + } + + private List mockSamples() { + var sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setPatientStableId(PATIENT_ID_1); + sample1.setCancerStudyIdentifier(STUDY_ID); + + var sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setPatientStableId(PATIENT_ID_2); + sample2.setCancerStudyIdentifier(STUDY_ID); + + var sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setPatientStableId(PATIENT_ID_3); + sample3.setCancerStudyIdentifier(STUDY_ID_2); + + return List.of(sample1, sample2, sample3); + } + + @Before + public void setup() { + ReflectionTestUtils.setField(federatedViewService, "federationMode", FederationMode.DATASOURCE); + + List attribs = mockClinicalAttributes(); + + // Methods used by fetchClinicalAttributes + } + + @Test + public void fetchClinicalAttributes() throws FederationException { + // Arrange + var expected = mockClinicalAttributes(); + + // Act + var result = federatedViewService.fetchClinicalAttributes(); + + // Assert + Assert.assertEquals(expected, result); + } + +// @Test +// public void fetchClinicalDataCountsNoFilter() throws FederationException { +// // Arrange +// // Mock out: the cohort, ie. +// // - 1 person is this race & this age & this study +// // - .. 2 other people .. +// var filter = new ClinicalDataCountFilter(); +// // First we get the cohort +//// Mockito.when( +//// studyViewFilterApplier.apply() +//// ).thenReturn( +//// +//// ); +// // Then we extract the study and sample IDs from this cohort +// Mockito.when().thenReturn(); +// // Then we call clinicalDataService +// Mockito.when( +// clinicalDataService.fetchClinicalDataCounts( +// studyIds, +// sampleIds, +// attributeIds +// ) +// ).thenReturn( +// /* ... */ +// ); +// +// // Act +// var result = federatedViewService.fetchClinicalDataCounts(filter); +// +// // Assert +// // - Returns some list of SampleIdentifiers +// // - Extracts them into study ID + sample ID list +// // - Calls fetchClinicalDataCounts() +// } +// +// // TODO test with filter +// +// @Test +// public void fetchClinicalDataBinCountsNoFilter() throws FederationException { +// // Arrange +// var filter = new ClinicalDataBinCountFilter(); +// Mockito.when( +// clinicalDataBinUtil.fetchClinicalDataBinCounts( +// DataBinMethod.STATIC, +// filter, +// false +// ) +// ).thenReturn( +// /* ... */ +// ); +// +// // Act +// var result = federatedViewService.fetchClinicalDataBinCounts(); +// +// // Assert ... +// } +// +// // TODO test with filter +} diff --git a/src/test/java/org/cbioportal/test/integration/FederatedApiIntegrationTest.java b/src/test/java/org/cbioportal/test/integration/FederatedApiIntegrationTest.java new file mode 100644 index 00000000000..30c6e171fcb --- /dev/null +++ b/src/test/java/org/cbioportal/test/integration/FederatedApiIntegrationTest.java @@ -0,0 +1,46 @@ +package org.cbioportal.test.integration; + +import org.cbioportal.model.ClinicalAttribute; +import org.cbioportal.model.Sample; +import org.cbioportal.persistence.ClinicalAttributeRepository; +import org.cbioportal.persistence.ClinicalDataRepository; +import org.cbioportal.persistence.SampleRepository; +import org.cbioportal.service.ClinicalDataService; +import org.cbioportal.service.FederatedViewService; +import org.cbioportal.web.FederatedViewController; +import org.cbioportal.web.config.TestConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@RunWith(SpringJUnit4ClassRunner.class) +//@WebMvcTest +//@AutoConfigureMockMvc // load the whole Spring Boot application context +@ContextConfiguration(classes = { + FederatedViewController.class, + FederatedViewService.class, + ClinicalDataService.class, + TestConfig.class +}) +public class FederatedApiIntegrationTest { +} diff --git a/src/test/java/org/cbioportal/web/FederatedViewControllerTest.java b/src/test/java/org/cbioportal/web/FederatedViewControllerTest.java new file mode 100644 index 00000000000..441d4ce3627 --- /dev/null +++ b/src/test/java/org/cbioportal/web/FederatedViewControllerTest.java @@ -0,0 +1,234 @@ +package org.cbioportal.web; + + +import org.cbioportal.model.AlterationCountByGene; +import org.cbioportal.model.AlterationFilter; +import org.cbioportal.model.ClinicalAttribute; +import org.cbioportal.model.Sample; +import org.cbioportal.persistence.ClinicalAttributeRepository; +import org.cbioportal.persistence.ClinicalDataRepository; +import org.cbioportal.persistence.SampleRepository; +import org.cbioportal.service.ClinicalDataService; +import org.cbioportal.service.FederatedViewService; +import org.cbioportal.service.impl.ClinicalAttributeServiceImpl; +import org.cbioportal.service.impl.ClinicalDataServiceImpl; +import org.cbioportal.service.impl.FederatedViewServiceImpl; +import org.cbioportal.service.util.MolecularProfileUtil; +import org.cbioportal.web.config.TestConfig; +import org.cbioportal.web.parameter.SampleIdentifier; +import org.cbioportal.web.parameter.StudyViewFilter; +import org.cbioportal.web.util.*; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +@ContextConfiguration(classes = { + FederatedViewController.class, + FederatedViewServiceImpl.class, + ClinicalDataServiceImpl.class, + ClinicalAttributeServiceImpl.class, + StudyViewFilterUtil.class, + StudyViewFilterApplier.class, + ClinicalDataBinUtil.class +}) +public class FederatedViewControllerTest { + + private final String STUDY_ID = "test_study_1"; + private final String STUDY_ID_2 = "test_study_2"; + + private final String PATIENT_ID_1 = "patient_id_1"; + private final String PATIENT_ID_2 = "patient_id_2"; + private final String PATIENT_ID_3 = "patient_id_3"; + + private final String SAMPLE_ID1 = "sample_id_1"; + private final String SAMPLE_ID2 = "sample_id_2"; + private final String SAMPLE_ID3 = "sample_id_3"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private FederatedViewService federatedViewService; + + @MockBean + private ClinicalAttributeRepository clinicalAttributeRepository; + + @MockBean + private SampleRepository sampleRepository; + + @MockBean + private ClinicalDataRepository clinicalDataRepository; + + + private List mockClinicalAttributes() { + + var attrib11 = new ClinicalAttribute(); + attrib11.setDisplayName("Sex"); + attrib11.setDescription("Sex"); + attrib11.setDatatype("STRING"); + attrib11.setPatientAttribute(false); + attrib11.setPriority("1"); + attrib11.setAttrId("SEX"); + attrib11.setCancerStudyIdentifier(STUDY_ID); + + var attrib21 = new ClinicalAttribute(); + attrib21.setDisplayName("Age"); + attrib21.setDescription("Age"); + attrib21.setDatatype("NUMBER"); + attrib21.setPatientAttribute(false); + attrib21.setPriority("1"); + attrib21.setAttrId("AGE"); + attrib21.setCancerStudyIdentifier(STUDY_ID); + + var attrib12 = new ClinicalAttribute(); + attrib12.setDisplayName("Sex"); + attrib12.setDescription("Sex"); + attrib12.setDatatype("STRING"); + attrib12.setPatientAttribute(false); + attrib12.setPriority("1"); + attrib12.setAttrId("SEX"); + attrib12.setCancerStudyIdentifier(STUDY_ID_2); + + var attrib22 = new ClinicalAttribute(); + attrib22.setDisplayName("Age"); + attrib22.setDescription("Age"); + attrib22.setDatatype("NUMBER"); + attrib22.setPatientAttribute(false); + attrib22.setPriority("1"); + attrib22.setAttrId("AGE"); + attrib22.setCancerStudyIdentifier(STUDY_ID_2); + + return List.of(attrib11, attrib21, attrib12, attrib22); + } + + private List mockSamples() { + var sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setPatientStableId(PATIENT_ID_1); + sample1.setCancerStudyIdentifier(STUDY_ID); + + var sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setPatientStableId(PATIENT_ID_2); + sample2.setCancerStudyIdentifier(STUDY_ID); + + var sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setPatientStableId(PATIENT_ID_3); + sample3.setCancerStudyIdentifier(STUDY_ID_2); + + return List.of(sample1, sample2, sample3); + } + + @Before + public void setup() { + List attribs = mockClinicalAttributes(); + List samples = mockSamples(); + + when( + clinicalAttributeRepository.fetchClinicalAttributes( + /* studyIds */ any(), + /* projection */ any() + ) + ).thenReturn( + attribs + ); + + // Methods used by fetchClinicalDataCounts + + // When cross-checking list of attributes requested + when( + clinicalAttributeRepository.getClinicalAttributesByStudyIdsAndAttributeIds( + /* studyIds */ any(), + /* attributeIds */ any() + ) + ).thenReturn( + attribs + ); + + // When applying the study view filter to get a list of samples + when( + sampleRepository.fetchSamples( + /* studyIds */ any(), + /* sampleIds */ any(), + /* projection */ any() + ) + ).thenReturn( + samples + ); + +// // When tallying the counts +// when( +// clinicalDataRepository.fetchClinicalDataCounts( +// /* studyIds */ any(), +// /* sampleIds */ any(), +// /* attributeIds */ any(), +// /* clinicalDataType */ any(), +// /* projection */ any() +// ) +// ).thenReturn( +// +// ); +// +// // Methods used by fetchClinicalDataBinCounts +// when( +// clinicalDataRepository.fetchClinicalData( +// /* studyIds */ any(), +// /* sampleIds */ any(), +// /* attributeIds */ any(), +// /* clinicalDataType */ any(), +// /* projection */ any() +// ) +// ); + } + + @Test + @WithMockUser + public void fetchClinicalAttributes() throws Exception { + + mockMvc.perform(MockMvcRequestBuilders.post("/api-fed/clinical-attributes/fetch").with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content("{}")) + .andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$[0].displayName").value("Sex")) + .andExpect(jsonPath("$[0].description").value("Sex")) + .andExpect(jsonPath("$[0].datatype").value("STRING")) + .andExpect(jsonPath("$[0].patientAttribute").value(true)) + .andExpect(jsonPath("$[0].priority").value("1")) + .andExpect(jsonPath("$[0].clinicalAttributeId").value("SEX")) + .andExpect(jsonPath("$[0].studyId").value(STUDY_ID)) + .andExpect(jsonPath("$[1].displayName").value("Age")) + .andExpect(jsonPath("$[1].description").value("Age")) + .andExpect(jsonPath("$[1].datatype").value("NUMBER")) + .andExpect(jsonPath("$[1].patientAttribute").value(true)) + .andExpect(jsonPath("$[1].priority").value("1")) + .andExpect(jsonPath("$[1].clinicalAttributeId").value("AGE")) + .andExpect(jsonPath("$[1].studyId").value(STUDY_ID)); + } +} diff --git a/src/test/java/org/cbioportal/web/config/TestConfig.java b/src/test/java/org/cbioportal/web/config/TestConfig.java index dee57c0420d..d6edb6d52b6 100644 --- a/src/test/java/org/cbioportal/web/config/TestConfig.java +++ b/src/test/java/org/cbioportal/web/config/TestConfig.java @@ -1,6 +1,9 @@ package org.cbioportal.web.config; import org.cbioportal.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.persistence.fedapi.FederatorConfig; +import org.cbioportal.service.FederatedViewService; +import org.cbioportal.service.impl.FederatedViewServiceImpl; import org.cbioportal.web.error.GlobalExceptionHandler; import org.cbioportal.web.util.InvolvedCancerStudyExtractorInterceptor; import org.springframework.beans.factory.annotation.Autowired; @@ -48,4 +51,14 @@ public CustomObjectMapper customObjectMapper() { public GlobalExceptionHandler globalExceptionHandler() { return new GlobalExceptionHandler(); } + + @Bean + public FederatedViewService federatedViewService() { + return new FederatedViewServiceImpl(); + } + + @Bean + public FederatorConfig federatorConfig() { + return new FederatorConfig(); + } }