package dbfit.diff;
import dbfit.util.MatchResult;
import dbfit.util.DiffListener;
import dbfit.util.DataRow;
import dbfit.util.DataCell;
import static dbfit.util.MatchStatus.*;
import static dbfit.util.DiffTestUtils.createDataRowBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.hamcrest.Matcher;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.Mock;
import org.mockito.Captor;
import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.*;
import java.util.List;
import java.util.ArrayList;
@RunWith(MockitoJUnitRunner.class)
public class DataRowDiffTest {
@Mock DataCellDiff childDiff;
@Mock MatchResult<DataRow, DataRow> mockResult;
@Mock DiffListener listener;
@Captor ArgumentCaptor<MatchResult> resultCaptor;
@Captor ArgumentCaptor<DataCell> arg1Captor;
@Captor ArgumentCaptor<DataCell> arg2Captor;
private List<MatchResult> allResults;
private String[] columns = new String[] { "n", "2n" };
private void runUnadaptedDiff(DataRow row1, DataRow row2) {
runUnadaptedDiff(row1, row2, columns);
}
private void runUnadaptedDiff(DataRow row1, DataRow row2, String... colNames) {
DataRowDiff diff = new DataRowDiff(colNames);
diff.addListener(listener);
diff.diff(row1, row2);
verify(listener, times(1 + colNames.length)).onEvent(resultCaptor.capture());
allResults = resultCaptor.getAllValues();
}
private void runWithMockedChildDiff(DataRow row1, DataRow row2) {
DataRowDiff diff = new DataRowDiff(columns, childDiff);
diff.diff(row1, row2);
verify(childDiff, times(columns.length)).diff(
arg1Captor.capture(), arg2Captor.capture());
}
@Test
public void shouldInvokeDiffPerEachChildCell() {
runWithMockedChildDiff(createRow(2, 4), createRow(3, 5));
assertThat(arg1Captor.getAllValues(), hasItems(2, 4));
assertThat(arg2Captor.getAllValues(), hasItems(3, 5));
}
@Test
public void onExceptionShouldEmitExceptionEvent() {
DataRowDiff diff = new DataRowDiff(columns, childDiff);
Exception ex = new RuntimeException("Cruel World!");
doThrow(ex).when(childDiff).diff(anyDataCell(), anyDataCell());
diff.diff(mockResult);
verify(mockResult).setException(ex);
}
@Test
public void numEventsShouldBeOnePerChildPlusSelf() {
runUnadaptedDiff(createRow(2, 4), createRow(2, 4));
assertEquals(3, allResults.size());
}
@Test
public void shouldEmitChildrenDiffEventsOfTypeDataCell() {
Class expectedType = DataCell.class;
runUnadaptedDiff(createRow(2, 4), createRow(2, 4));
assertThat(allResults.get(0).getType(), equalTo(expectedType));
assertThat(allResults.get(1).getType(), equalTo(expectedType));
}
@Test
public void shouldEmitDiffEventOfTypeDataRow() {
Class expectedType = DataRow.class;
runUnadaptedDiff(createRow(2, 4), createRow(2, 4));
assertThat(allResults.get(2).getType(), equalTo(expectedType));
}
private DataRow createRow(Integer... items) {
return createDataRowBuilder(columns).createRow(items);
}
public static <E> Matcher<Iterable<? extends E>> hasItems(Object... values) {
List<Matcher<? super E>> matchers = new ArrayList<>();
for (Object item : values) {
matchers.add(hasToString(String.valueOf(item)));
}
return contains(matchers);
}
private DataCell anyDataCell() {
return org.mockito.ArgumentMatchers.any();
}
}