package uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import uk.ac.ox.zoo.seeg.abraid.mp.common.domain.*;
import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.DiseaseService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.*;
/**
* Tests the DiseaseOccurrenceReviewManager class.
* Copyright (c) 2014 University of Oxford
*/
public class DiseaseOccurrenceReviewManagerTest {
private static final int DISEASE_GROUP_ID = 1;
private double expertWeightingThreshold = 0.5;
@Test
public void updateDiseaseOccurrenceStatusRemainsInReviewWhenMoreThanMaxDaysHasNotElapsedSinceCreatedDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(0);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.IN_REVIEW, 7);
}
@Test
public void updateDiseaseOccurrenceStatusRemainsInReviewWhenMoreThanMaxDaysHasNotElapsedSinceCreatedDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(0);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.IN_REVIEW, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsReadyWhenMaxDaysHasElapsedSinceCreatedDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(5);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.READY, 5);
}
@Test
public void updateDiseaseOccurrenceStatusSetsDiscardedWhenMaxDaysHasElapsedSinceCreatedDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(6);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED, 6);
}
@Test
public void updateDiseaseOccurrenceStatusSetsReadyWhenMoreThanMaxDaysHasElapsedSinceCreatedDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(9);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.READY, 8);
}
@Test
public void updateDiseaseOccurrenceStatusSetsDiscardedWhenMoreThanMaxDaysHasElapsedSinceCreatedDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(21);
DateTime automaticModelRunsStartDate = createdDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED, 15);
}
@Test
public void updateDiseaseOccurrenceStatusRemainsInReviewWhenMoreThanMaxDaysHasNotElapsedSinceAutomaticModelRunsStartDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(0);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.IN_REVIEW, 7);
}
@Test
public void updateDiseaseOccurrenceStatusRemainsInReviewWhenMoreThanMaxDaysHasNotElapsedSinceAutomaticModelRunsStartDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(0);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.IN_REVIEW, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsReadyWhenMaxDaysHasElapsedSinceCreatedDateSinceAutomaticModelRunsStartDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(7);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.READY, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsDiscardedWhenMaxDaysHasElapsedSinceCreatedDateSinceAutomaticModelRunsStartDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(7);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsReadyWhenMoreThanMaxDaysHasElapsedSinceCreatedDateSinceAutomaticModelRunsStartDate() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(8);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, true, DiseaseOccurrenceStatus.READY, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsDiscardedWhenMoreThanMaxDaysHasElapsedSinceCreatedDateSinceAutomaticModelRunsStartDateAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime automaticModelRunsStartDate = lastModelRunPrepDate.minusDays(8);
DateTime createdDate = automaticModelRunsStartDate.minusDays(2);
DiseaseOccurrence occurrence = arrangeDates(createdDate, automaticModelRunsStartDate, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, true, false, DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsReadyWhenAutomaticModelRunsNotEnabled() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(0);
DiseaseOccurrence occurrence = arrangeDates(createdDate, null, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, false, true, DiseaseOccurrenceStatus.READY, 7);
}
@Test
public void updateDiseaseOccurrenceStatusSetsDiscardedWhenAutomaticModelRunsNotEnabledAndOccurrenceNotReviewed() {
// Arrange
DateTime lastModelRunPrepDate = DateTime.now();
DateTime createdDate = lastModelRunPrepDate.minusDays(0);
DiseaseOccurrence occurrence = arrangeDates(createdDate, null, lastModelRunPrepDate);
// Act and Assert
executeTest(occurrence, false, false, DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED, 7);
}
private DiseaseOccurrence arrangeDates(DateTime createdDate, DateTime automaticModelRunsStartDate, DateTime lastModelRunPrepDate) {
DiseaseGroup diseaseGroup = mock(DiseaseGroup.class);
when(diseaseGroup.getId()).thenReturn(DISEASE_GROUP_ID);
when(diseaseGroup.getAutomaticModelRunsStartDate()).thenReturn(automaticModelRunsStartDate);
when(diseaseGroup.getLastModelRunPrepDate()).thenReturn(lastModelRunPrepDate);
DiseaseOccurrence occurrence = mock(DiseaseOccurrence.class);
when(occurrence.getStatus()).thenReturn(DiseaseOccurrenceStatus.IN_REVIEW);
when(occurrence.getCreatedDate()).thenReturn(createdDate);
when(occurrence.getDiseaseGroup()).thenReturn(diseaseGroup);
return occurrence;
}
private void executeTest(DiseaseOccurrence occurrence, boolean isAutomaticProcess, boolean hasBeenReviewed,
DiseaseOccurrenceStatus expectedStatus, int maxDays) {
// Arrange
DiseaseService diseaseService = mockDiseaseService(occurrence, hasBeenReviewed, maxDays);
DiseaseOccurrenceReviewManager target = new DiseaseOccurrenceReviewManager(diseaseService, expertWeightingThreshold);
// Act
target.updateDiseaseOccurrenceStatus(DISEASE_GROUP_ID, isAutomaticProcess);
// Assert
int expectedTimes = (expectedStatus == DiseaseOccurrenceStatus.READY ||
expectedStatus == DiseaseOccurrenceStatus.DISCARDED_UNREVIEWED) ? 1 : 0;
verify(occurrence, times(expectedTimes)).setStatus(expectedStatus);
verify(diseaseService, times(expectedTimes)).saveDiseaseOccurrence(occurrence);
}
private DiseaseService mockDiseaseService(DiseaseOccurrence occurrence, boolean hasBeenReviewed, final int maxDays) {
DiseaseService diseaseService = mock(DiseaseService.class);
when(diseaseService.getDiseaseOccurrencesInValidation(DISEASE_GROUP_ID)).thenReturn(Arrays.asList(occurrence));
List<DiseaseOccurrenceReview> reviews = new ArrayList<>();
if (hasBeenReviewed) {
reviews.add(new DiseaseOccurrenceReview(mock(Expert.class), occurrence, DiseaseOccurrenceReviewResponse.UNSURE));
}
when(diseaseService.getDiseaseOccurrenceReviewsForOccurrencesInValidationForUpdatingWeightings(DISEASE_GROUP_ID, expertWeightingThreshold)).thenReturn(reviews);
when(diseaseService.subtractMaxDaysOnValidator(any(DateTime.class))).thenAnswer(new Answer<LocalDate>() {
@Override
public LocalDate answer(InvocationOnMock invocationOnMock) throws Throwable {
return ((DateTime) invocationOnMock.getArguments()[0]).toLocalDate().minusDays(maxDays);
}
});
return diseaseService;
}
}