diff --git a/app/src/main/java/uk/ac/ebi/atlas/search/JsonGeneSearchController.java b/app/src/main/java/uk/ac/ebi/atlas/search/JsonGeneSearchController.java index b96eb1a45..460bacf38 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/search/JsonGeneSearchController.java +++ b/app/src/main/java/uk/ac/ebi/atlas/search/JsonGeneSearchController.java @@ -17,7 +17,7 @@ import uk.ac.ebi.atlas.controllers.JsonExceptionHandlingController; import uk.ac.ebi.atlas.experimentpage.ExperimentAttributesService; import uk.ac.ebi.atlas.model.experiment.singlecell.SingleCellBaselineExperiment; -import uk.ac.ebi.atlas.search.analytics.AnalyticsSearchService; +import uk.ac.ebi.atlas.search.celltype.CellTypeSearchService; import uk.ac.ebi.atlas.search.geneids.GeneIdSearchService; import uk.ac.ebi.atlas.search.geneids.QueryParsingException; import uk.ac.ebi.atlas.search.organismpart.OrganismPartSearchService; @@ -47,8 +47,8 @@ public class JsonGeneSearchController extends JsonExceptionHandlingController { private final ExperimentTrader experimentTrader; private final ExperimentAttributesService experimentAttributesService; - private final AnalyticsSearchService analyticsSearchService; private final OrganismPartSearchService organismPartSearchService; + private final CellTypeSearchService cellTypeSearchService; private final SpeciesSearchService speciesSearchService; @GetMapping(value = "/json/search", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @@ -267,7 +267,10 @@ public Set getCellTypeBySearchTerm(@RequestParam MultiValueMap getInferredCellTypeAuthorsLabels(String experimentAc */ private ImmutableSet getCellTypeMetadata(String experimentAccession, ImmutableSet organOrOrganismPart, - String cellTypeValue) { + String cellTypeFacetName) { var cellIdsInOrganOrOrganismPartQueryBuilder = new SolrQueryBuilder() .addQueryFieldByTerm(EXPERIMENT_ACCESSION, experimentAccession) @@ -124,8 +126,8 @@ private ImmutableSet getCellTypeMetadata(String experimentAccession, .addQueryFieldByTerm(EXPERIMENT_ACCESSION, experimentAccession) .addQueryFieldByTerm( ImmutableMap.of( - FACET_FACTOR_NAME, ImmutableSet.of(cellTypeValue), - FACET_CHARACTERISTIC_NAME, ImmutableSet.of(cellTypeValue))) + FACET_FACTOR_NAME, ImmutableSet.of(cellTypeFacetName), + FACET_CHARACTERISTIC_NAME, ImmutableSet.of(cellTypeFacetName))) .setFieldList(ImmutableSet.of(CELL_ID, FACET_FACTOR_VALUE, FACET_CHARACTERISTIC_VALUE)) .sortBy(CELL_ID, SolrQuery.ORDER.asc); var uniqueCellIdsAnnotatedWithCellTypeValue = @@ -162,4 +164,45 @@ private ImmutableSet getCellTypeMetadata(String experimentAccession, .collect(toImmutableSet()); } } + + public ImmutableSet searchCellTypes(ImmutableSet cellIds, ImmutableSet organismParts) { +// Streaming query for getting the cell types provided by set of cell IDs and organism parts +// unique( +// search(scxa-analytics-v6, q=cell_id: AND ctw_organism_part:, +// fl="ctw_cell_type", +// sort="ctw_cell_type asc" +// ), +// over="ctw_cell_type" +// ) + return getCellTypeFromStreamQuery( + new UniqueStreamBuilder(getStreamBuilderForCellTypeByCellIdsAndOrganismParts( + cellIds, organismParts), CTW_CELL_TYPE.name())); + } + + private SearchStreamBuilder getStreamBuilderForCellTypeByCellIdsAndOrganismParts( + ImmutableSet cellIDs, ImmutableSet organismParts) { + var cellTypeQueryBuilder = new SolrQueryBuilder() + .addQueryFieldByTerm(CELL_ID, cellIDs) + .setFieldList(CTW_CELL_TYPE) + .sortBy(CTW_CELL_TYPE, SolrQuery.ORDER.asc); + + if (organismParts != null && !organismParts.isEmpty()) { + cellTypeQueryBuilder.addQueryFieldByTerm(CTW_ORGANISM_PART, organismParts); + } + + return new SearchStreamBuilder<>( + singleCellAnalyticsCollectionProxy, + cellTypeQueryBuilder + ).returnAllDocs(); + } + + private ImmutableSet getCellTypeFromStreamQuery(UniqueStreamBuilder uniqueCellTypeStreamBuilder) { + try (TupleStreamer tupleStreamer = TupleStreamer.of(uniqueCellTypeStreamBuilder.build())) { + return tupleStreamer.get() + .filter(tuple -> !tuple.getFields().isEmpty()) + .map(tuple -> tuple.getString(CTW_CELL_TYPE.name())) + .collect(toImmutableSet() + ); + } + } } \ No newline at end of file diff --git a/app/src/main/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchService.java b/app/src/main/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchService.java new file mode 100644 index 000000000..b06c536c8 --- /dev/null +++ b/app/src/main/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchService.java @@ -0,0 +1,29 @@ +package uk.ac.ebi.atlas.search.celltype; + +import com.google.common.collect.ImmutableSet; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import uk.ac.ebi.atlas.search.GeneSearchService; + +@Component +@RequiredArgsConstructor +public class CellTypeSearchService { + + private final CellTypeSearchDao cellTypeSearchDao; + private final GeneSearchService geneSearchService; + + private static final Logger LOGGER = LoggerFactory.getLogger(CellTypeSearchService.class); + + public ImmutableSet search(ImmutableSet geneIds, ImmutableSet organismParts) { + if (geneIds.isEmpty()) { + LOGGER.warn("Can't query for organism part as no gene IDs has given."); + return ImmutableSet.of(); + } + + LOGGER.info("Searching organism parts for this gene ids: {}", geneIds.asList()); + + return cellTypeSearchDao.searchCellTypes(geneSearchService.getCellIdsFromGeneIds(geneIds), organismParts); + } +} diff --git a/app/src/main/java/uk/ac/ebi/atlas/search/organismpart/OrganismPartSearchDao.java b/app/src/main/java/uk/ac/ebi/atlas/search/organismpart/OrganismPartSearchDao.java index fe5bfff10..81b31556a 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/search/organismpart/OrganismPartSearchDao.java +++ b/app/src/main/java/uk/ac/ebi/atlas/search/organismpart/OrganismPartSearchDao.java @@ -25,10 +25,10 @@ public OrganismPartSearchDao(SolrCloudCollectionProxyFactory collectionProxyFact collectionProxyFactory.create(SingleCellAnalyticsCollectionProxy.class); } - public ImmutableSet searchOrganismPart(ImmutableSet cellIDs, ImmutableSet cellTypes) { -// Streaming query for getting the organism_part provided by set of cell IDs + public ImmutableSet searchOrganismPart(ImmutableSet cellIDs, ImmutableSet cellTypes) { +// Streaming query for getting the organism_part provided by set of cell IDs and cell types // unique( -// search(scxa-analytics-v6, q=cell_id: AND cell_type:, +// search(scxa-analytics-v6, q=cell_id: AND ctw_cell_type:, // fl="ctw_organism_part", // sort="ctw_organism_part asc" // ), diff --git a/app/src/main/java/uk/ac/ebi/atlas/solr/SingleCellSolrUtils.java b/app/src/main/java/uk/ac/ebi/atlas/solr/SingleCellSolrUtils.java index 781f1fa82..8d16dcf90 100644 --- a/app/src/main/java/uk/ac/ebi/atlas/solr/SingleCellSolrUtils.java +++ b/app/src/main/java/uk/ac/ebi/atlas/solr/SingleCellSolrUtils.java @@ -13,6 +13,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import static uk.ac.ebi.atlas.solr.cloud.collections.SingleCellAnalyticsCollectionProxy.CELL_ID; import static uk.ac.ebi.atlas.solr.cloud.collections.SingleCellAnalyticsCollectionProxy.CTW_CELL_TYPE; +import static uk.ac.ebi.atlas.solr.cloud.collections.SingleCellAnalyticsCollectionProxy.CTW_ORGANISM_PART; @Component public class SingleCellSolrUtils { @@ -33,12 +34,32 @@ public ImmutableSet fetchedRandomCellTypesByCellIDs(ImmutableSet .setFieldList(CTW_CELL_TYPE) .setRows(MAX_ROWS); - return getRandomCellTypesFromQueryResult(singleCellAnalyticsCollectionProxy.query(queryBuilder).getResults(), numberOfCellTypes); + return getRandomCellTypesFromQueryResult( + singleCellAnalyticsCollectionProxy.query(queryBuilder).getResults(), + CTW_CELL_TYPE.name(), + numberOfCellTypes); } - private ImmutableSet getRandomCellTypesFromQueryResult(SolrDocumentList solrDocumentList, int numberOfCellTypes) { + public ImmutableSet fetchedRandomOrganismPartsByCellIDs(ImmutableSet cellIDs, int numberOfOrganismParts) { + SolrQueryBuilder queryBuilder = new SolrQueryBuilder<>(); + queryBuilder + .addQueryFieldByTerm(CELL_ID, cellIDs) + .setFieldList(CTW_ORGANISM_PART) + .setRows(MAX_ROWS); + + return getRandomCellTypesFromQueryResult( + singleCellAnalyticsCollectionProxy.query(queryBuilder).getResults(), + CTW_ORGANISM_PART.name(), + numberOfOrganismParts); + } + + + private ImmutableSet getRandomCellTypesFromQueryResult( + SolrDocumentList solrDocumentList, + String schemaFieldName, + int numberOfCellTypes) { return Arrays.stream(new Random().ints(numberOfCellTypes, 0, solrDocumentList.size()).toArray()) - .mapToObj(index -> solrDocumentList.get(index).getFieldValue(CTW_CELL_TYPE.name()).toString()) + .mapToObj(index -> solrDocumentList.get(index).getFieldValue(schemaFieldName).toString()) .collect(toImmutableSet()); } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerIT.java b/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerIT.java index a8900d47a..b8517c49a 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerIT.java @@ -14,7 +14,7 @@ import org.springframework.util.LinkedMultiValueMap; import uk.ac.ebi.atlas.configuration.TestConfig; import uk.ac.ebi.atlas.experimentpage.ExperimentAttributesService; -import uk.ac.ebi.atlas.search.analytics.AnalyticsSearchService; +import uk.ac.ebi.atlas.search.celltype.CellTypeSearchService; import uk.ac.ebi.atlas.search.geneids.GeneIdSearchService; import uk.ac.ebi.atlas.search.geneids.GeneQuery; import uk.ac.ebi.atlas.search.geneids.QueryParsingException; @@ -45,12 +45,11 @@ class JsonGeneSearchControllerIT { @Mock private GeneSearchService geneSearchServiceMock; - @Mock - private AnalyticsSearchService analyticsSearchServiceMock; - @Mock private OrganismPartSearchService organismPartSearchServiceMock; + @Mock + private CellTypeSearchService cellTypeSearchService; @Inject private ExperimentTrader experimentTrader; @@ -71,8 +70,8 @@ void setUp() { geneSearchServiceMock, experimentTrader, experimentAttributesService, - analyticsSearchServiceMock, organismPartSearchServiceMock, + cellTypeSearchService, speciesSearchService); } @@ -254,7 +253,7 @@ void whenSearchTermIsFoundAndThereAreRelatedCellIdsThenReturnsOrganismParts() { } @Test - void whenRequestParamIsEmptyCellTypeSearchReturnsEmptySet() { + void whenRequestParamIsEmptyCellTypeSearchReturnsException() { var requestParams = new LinkedMultiValueMap(); when(geneIdSearchServiceMock.getGeneQueryByRequestParams(requestParams)) @@ -277,7 +276,7 @@ void whenSearchTermIsNotFoundAnyGeneIdsCellTypeSearchReturnsEmptySet() { .thenReturn(geneQuery); when(geneIdSearchServiceMock.search(geneQuery)) .thenReturn(Optional.of(ImmutableSet.of())); - when(analyticsSearchServiceMock.searchCellType(ImmutableSet.of())) + when(cellTypeSearchService.search(ImmutableSet.of(), ImmutableSet.of())) .thenReturn(ImmutableSet.of()); var emptyCellTypeSet = subject.getCellTypeBySearchTerm(requestParams); @@ -299,7 +298,7 @@ void whenSearchTermIsFoundButNoRelatedCellIdsThenCellTypeSearchReturnsEmptySet() .thenReturn(geneQuery); when(geneIdSearchServiceMock.search(geneQuery)) .thenReturn(Optional.of(geneIdsFromService)); - when(analyticsSearchServiceMock.searchCellType(geneIdsFromService)) + when(cellTypeSearchService.search(geneIdsFromService, ImmutableSet.of())) .thenReturn(ImmutableSet.of()); var emptyCellTypeSet = subject.getCellTypeBySearchTerm(requestParams); @@ -322,7 +321,7 @@ void whenSearchTermIsFoundAndThereAreRelatedCellIdsThenReturnsCellTypes() { .thenReturn(geneQuery); when(geneIdSearchServiceMock.search(geneQuery)) .thenReturn(Optional.of(geneIdsFromService)); - when(analyticsSearchServiceMock.searchCellType(geneIdsFromService)) + when(cellTypeSearchService.search(geneIdsFromService, ImmutableSet.of())) .thenReturn(ImmutableSet.of(expectedCellType)); var actualCellTypes = subject.getCellTypeBySearchTerm(requestParams); diff --git a/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerWIT.java b/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerWIT.java index bfe032c5a..94393d9f0 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerWIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/search/JsonGeneSearchControllerWIT.java @@ -1,6 +1,7 @@ package uk.ac.ebi.atlas.search; import com.google.common.collect.ImmutableSet; +import org.hamcrest.core.IsNull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -29,6 +30,7 @@ import javax.inject.Inject; import javax.sql.DataSource; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; @@ -346,4 +348,14 @@ void whenSearchTermExistsInDBThenReturnsSetOfCellType() throws Exception { .andExpect(jsonPath("$", hasSize(equalTo(expectedCellTypes.size())))) .andExpect(jsonPath("$", containsInAnyOrder(expectedCellTypes.toArray()))); } + + @Test + void whenGivenExistingSymbolReturnedCellTypesNotContainsNullValue() throws Exception { + var symbolValue = "CFTR"; + + this.mockMvc.perform(get("/json/gene-search/cell-types").param("symbol", symbolValue)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(jsonPath("$", not(contains(IsNull.nullValue())))); + } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchDaoIT.java b/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchDaoIT.java index 02c606d19..700f7a1ae 100644 --- a/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchDaoIT.java +++ b/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchDaoIT.java @@ -13,12 +13,15 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.web.WebAppConfiguration; import uk.ac.ebi.atlas.configuration.TestConfig; +import uk.ac.ebi.atlas.solr.SingleCellSolrUtils; import uk.ac.ebi.atlas.solr.cloud.SolrCloudCollectionProxyFactory; import uk.ac.ebi.atlas.testutils.JdbcUtils; import javax.inject.Inject; import javax.sql.DataSource; +import java.util.HashSet; + import static org.assertj.core.api.Assertions.assertThat; @WebAppConfiguration @@ -30,6 +33,9 @@ class CellTypeSearchDaoIT { @Inject private JdbcUtils jdbcUtils; + @Inject + private SingleCellSolrUtils solrUtils; + @Inject private DataSource dataSource; @@ -42,6 +48,7 @@ class CellTypeSearchDaoIT { void populateDatabaseTables() { var populator = new ResourceDatabasePopulator(); populator.addScripts( + new ClassPathResource("fixtures/experiment.sql"), new ClassPathResource("fixtures/scxa_analytics.sql") ); @@ -52,7 +59,8 @@ void populateDatabaseTables() { void cleanDatabaseTables() { var populator = new ResourceDatabasePopulator(); populator.addScripts( - new ClassPathResource("fixtures/scxa_analytics-delete.sql") + new ClassPathResource("fixtures/scxa_analytics-delete.sql"), + new ClassPathResource("fixtures/experiment-delete.sql") ); populator.execute(dataSource); } @@ -64,9 +72,10 @@ void setUp() { @Test void nonExistentValueReturnsEmptyCollection() { - assertThat(subject.getInferredCellTypeOntologyLabels("E-MTAB-5061", ImmutableSet.of("foobar"))) + var experimentAccessions = jdbcUtils.fetchRandomExperimentAccession(); + assertThat(subject.getInferredCellTypeOntologyLabels(experimentAccessions, ImmutableSet.of("foobar"))) .isEmpty(); - assertThat(subject.getInferredCellTypeAuthorsLabels("E-MTAB-5061", ImmutableSet.of("foobar"))) + assertThat(subject.getInferredCellTypeAuthorsLabels(experimentAccessions, ImmutableSet.of("foobar"))) .isEmpty(); } @@ -118,7 +127,67 @@ void ontologyLabelsAcceptMultipleOrganismParts(){ void authorsLabelsAcceptMultipleOrganismParts(){ var authorsLabels = subject.getInferredCellTypeAuthorsLabels( - "E-MTAB-5061", ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0000006","http://purl.obolibrary.org/obo/UBERON_0001264")); + "E-MTAB-5061", + ImmutableSet.of("http://purl.obolibrary.org/obo/UBERON_0000006", + "http://purl.obolibrary.org/obo/UBERON_0001264")); assertThat(authorsLabels).isNotEmpty(); } + + @Test + void whenEmptySetOfCellIDsAndOrganismPartsProvidedReturnEmptySetOfCellTypes() { + ImmutableSet emptyCellIDs = ImmutableSet.of(); + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + var cellTypes = subject.searchCellTypes(emptyCellIDs, emptySetOfOrganismParts); + + assertThat(cellTypes).isEmpty(); + } + + @Test + void whenInvalidCellIdsAndNoOrganismPartsProvidedReturnEmptySetOfCellTypes() { + var invalidCellIDs = + ImmutableSet.of("invalid-cellID-1", "invalid-cellID-2", "invalid-cellID-3"); + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + var cellTypes = subject.searchCellTypes(invalidCellIDs, emptySetOfOrganismParts); + + assertThat(cellTypes).isEmpty(); + } + + @Test + void whenOnlyValidCellIdsButNoOrganismPartsProvidedReturnSetOfCellTypes() { + var randomListOfCellIDs = + ImmutableSet.copyOf( + new HashSet<>(jdbcUtils.fetchRandomListOfCells(10))); + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + var cellTypes = subject.searchCellTypes(randomListOfCellIDs, emptySetOfOrganismParts); + + assertThat(cellTypes.size()).isGreaterThan(0); + } + + @Test + void whenValidCellIdsButInvalidOrganismPartsProvidedReturnEmptySetOfCellTypes() { + var randomListOfCellIDs = + ImmutableSet.copyOf( + new HashSet<>(jdbcUtils.fetchRandomListOfCells(10))); + ImmutableSet invalidOrganismParts = ImmutableSet.of("invalid-cellType-1", "invalid-cellType-2"); + + var cellTypes = subject.searchCellTypes(randomListOfCellIDs, invalidOrganismParts); + + assertThat(cellTypes).isEmpty(); + } + + @Test + void whenValidCellIdsAndValidProvidedReturnSetOfCellTypes() { + var randomListOfCellIDs = + ImmutableSet.copyOf( + new HashSet<>(jdbcUtils.fetchRandomListOfCells(3))); + ImmutableSet organismParts = solrUtils.fetchedRandomOrganismPartsByCellIDs( + randomListOfCellIDs, 1); + + var cellTypes = subject.searchCellTypes(randomListOfCellIDs, organismParts); + + assertThat(cellTypes.size()).isGreaterThan(0); + } } diff --git a/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchServiceTest.java b/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchServiceTest.java new file mode 100644 index 000000000..3979f4fc5 --- /dev/null +++ b/app/src/test/java/uk/ac/ebi/atlas/search/celltype/CellTypeSearchServiceTest.java @@ -0,0 +1,105 @@ +package uk.ac.ebi.atlas.search.celltype; + +import com.google.common.collect.ImmutableSet; +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.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import uk.ac.ebi.atlas.search.GeneSearchService; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class CellTypeSearchServiceTest { + + @Mock + private CellTypeSearchDao cellTypeSearchDao; + + @Mock + private GeneSearchService geneSearchService; + + private CellTypeSearchService subject; + + @BeforeEach + void setup() { + subject = new CellTypeSearchService(cellTypeSearchDao, geneSearchService); + } + + @Test + void whenEmptySetOfGeneIdsAndOrganismPartsProvidedReturnsEmptySetOfCellTypes() { + ImmutableSet emptySetOfGeneIds = ImmutableSet.of(); + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + var cellTypes = subject.search(emptySetOfGeneIds, emptySetOfOrganismParts); + + assertThat(cellTypes).isEmpty(); + } + + @Test + void whenNonExistentGeneIdsAndEmptySetOfOrganismPartsProvidedReturnsEmptySetOfCellTypes() { + var nonExistentGeneId = "nonExistentGeneId"; + var setOfNonExistentGeneIds = ImmutableSet.of(nonExistentGeneId); + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + when(geneSearchService.getCellIdsFromGeneIds(setOfNonExistentGeneIds)) + .thenReturn(ImmutableSet.of()); + when(cellTypeSearchDao.searchCellTypes(ImmutableSet.of(), emptySetOfOrganismParts)) + .thenReturn(ImmutableSet.of()); + + var cellTypes = subject.search(setOfNonExistentGeneIds, emptySetOfOrganismParts); + + assertThat(cellTypes).isEmpty(); + } + + @Test + void whenValidGeneIdsAndEmptySetOfOrganismPartsProvidedReturnsSetOfCellTypes() { + var existingGeneId1 = "ExistingGeneId1"; + var existingGeneId2 = "ExistingGeneId2"; + var geneIds = ImmutableSet.of(existingGeneId1, existingGeneId2); + var existingCellId1 = "ExistingCellId1"; + var existingCellId2 = "ExistingCellId2"; + var cellIds = ImmutableSet.of(existingCellId1, existingCellId2); + + ImmutableSet emptySetOfOrganismParts = ImmutableSet.of(); + + var expectedCellType = "root cortex 7"; + + when(geneSearchService.getCellIdsFromGeneIds(geneIds)) + .thenReturn(cellIds); + when(cellTypeSearchDao.searchCellTypes(cellIds, emptySetOfOrganismParts)) + .thenReturn(ImmutableSet.of(expectedCellType)); + + var cellTypes = subject.search(geneIds, emptySetOfOrganismParts); + + assertThat(cellTypes).contains(expectedCellType); + } + + @Test + void whenValidGeneIDsAndOrganismPartsProvidedReturnsSetOfCellTypes() { + var existingGeneId1 = "ExistingGeneId1"; + var existingGeneId2 = "ExistingGeneId2"; + var geneIds = ImmutableSet.of(existingGeneId1, existingGeneId2); + var existingCellId1 = "ExistingCellId1"; + var existingCellId2 = "ExistingCellId2"; + var cellIds = ImmutableSet.of(existingCellId1, existingCellId2); + var existingCellType1 = "ExistingCellType1"; + var existingCellType2 = "ExistingCellType2"; + var organismParts = ImmutableSet.of(existingCellType1, existingCellType2); + + var expectedCellType = "root cortex 7"; + + when(geneSearchService.getCellIdsFromGeneIds(geneIds)) + .thenReturn(cellIds); + when(cellTypeSearchDao.searchCellTypes(cellIds, organismParts)) + .thenReturn(ImmutableSet.of(expectedCellType)); + + var cellTypes = subject.search(geneIds, organismParts); + + assertThat(cellTypes).contains(expectedCellType); + } +}