package de.asideas.crowdsource.repository; import de.asideas.crowdsource.config.MongoDBConfig; import de.asideas.crowdsource.domain.model.ProjectEntity; import de.asideas.crowdsource.domain.model.UserEntity; import de.asideas.crowdsource.domain.shared.ProjectStatus; import de.asideas.crowdsource.presentation.statistics.results.BarChartStatisticsResult; import de.asideas.crowdsource.testsupport.CrowdSourceTestConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.EnumMap; import java.util.List; import java.util.Map; import static de.asideas.crowdsource.domain.shared.ProjectStatus.FULLY_PLEDGED; import static de.asideas.crowdsource.domain.shared.ProjectStatus.PROPOSED; import static de.asideas.crowdsource.domain.shared.ProjectStatus.PUBLISHED; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {MongoDBConfig.class, CrowdSourceTestConfig.class}) @IntegrationTest public class ProjectRepositoryImplIT { private static final Logger log = LoggerFactory.getLogger(ProjectRepositoryImplIT.class); @Autowired ProjectRepository projectRepository; @Autowired UserRepository userRepository; private UserEntity projectCreator; @Before public void init() { if (projectCreator == null) { List<UserEntity> allUsers = userRepository.findAll(); if (! allUsers.isEmpty()) { projectCreator = allUsers.get(0); } else { projectCreator = userRepository.save(new UserEntity("test@crowdsource.de")); } } } @Test public void sumProjectsGroupedByStatus_aggregation_returns_uptodate_data() { // Actually the aggregation should return same results as simply doing a count query for each separate status. Map<ProjectStatus, Long> initialCountsByStatus = getProjectCountsByStatus(); int addProposed = 30; int addPledged = 10; int addPublished = 50; givenProjectsWithStatus(addProposed, PROPOSED); givenProjectsWithStatus(addPledged, FULLY_PLEDGED); givenProjectsWithStatus(addPublished, PUBLISHED); log.info("|-- ALL PROJECTS CURRENTLY IN REPO: "); projectRepository.findAll().stream().forEach(e -> log.info(" -- " + e)); List<BarChartStatisticsResult> aggregationResult = projectRepository.sumProjectsGroupedByStatus(); expectAggregatedCount(aggregationResult, PROPOSED, initialCountsByStatus.get(PROPOSED) + addProposed); expectAggregatedCount(aggregationResult, PUBLISHED, initialCountsByStatus.get(PUBLISHED) + addPublished); expectAggregatedCount(aggregationResult, FULLY_PLEDGED, initialCountsByStatus.get(FULLY_PLEDGED) + addPledged); } @Test public void sumProjectsGroupedByStatus_aggregation_returns_unchanged_data() { // Assure at least 1 project exists in db for each status to test. givenProjectsWithStatus(1, PROPOSED); givenProjectsWithStatus(1, FULLY_PLEDGED); givenProjectsWithStatus(1, PUBLISHED); // Actually the aggregation should return same results as simply doing a count query for each separate status. Map<ProjectStatus, Long> initialCountsByStatus = getProjectCountsByStatus(); List<BarChartStatisticsResult> aggregationResult = projectRepository.sumProjectsGroupedByStatus(); expectAggregatedCount(aggregationResult, PROPOSED, initialCountsByStatus.get(PROPOSED)); expectAggregatedCount(aggregationResult, PUBLISHED, initialCountsByStatus.get(PUBLISHED)); expectAggregatedCount(aggregationResult, FULLY_PLEDGED, initialCountsByStatus.get(FULLY_PLEDGED)); } private void expectAggregatedCount(List<BarChartStatisticsResult> aggregationResult, ProjectStatus statusToTest, long expectedCount) { assertThat( aggregationResult.stream().filter(r -> statusToTest.name().equals(r.getId())).findFirst().get().getCount(), is(expectedCount) ); } private Map<ProjectStatus, Long> getProjectCountsByStatus() { EnumMap<ProjectStatus, Long> result = new EnumMap<>(ProjectStatus.class); for (ProjectStatus status : ProjectStatus.values()) { result.put(status, (long) projectRepository.findByStatusOrderByCreatedDateDesc(status).size()); } return result; } private void givenProjectsWithStatus(int desiredProjectCount, ProjectStatus desiredStatus) { for (int i = 0; i < desiredProjectCount; i++) { ProjectEntity project = new ProjectEntity(); project.setCreator(projectCreator); project.setTitle("project from ProjectRepositoryImplIT idx" + i); project.setDescription("project from ProjectRepositoryImplIT idx" + i); project.setPledgeGoal(1000); project.setStatus(desiredStatus); projectRepository.save(project); } } }