mardi 23 décembre 2014

Mockito: Mocking package private classes

I have the following simple DynamoDBDao which contains one method that queries an index and returns a map of results.



import com.amazonaws.services.dynamodbv2.document.*;

public class DynamoDBDao implements Dao{
private Table table;
private Index regionIndex;

public DynamoDBDao(Table table) {
this.table = table;
}

@PostConstruct
void initialize(){
this.regionIndex = table.getIndex(GSI_REGION_INDEX);
}

@Override
public Map<String, Long> read(String region) {
ItemCollection<QueryOutcome> items = regionIndex.query(ATTR_REGION, region);
Map<String, Long> results = new HashMap<>();
for (Item item : items) {
String key = item.getString(PRIMARY_KEY);
long value = item.getLong(ATTR_VALUE);
results.put(key, value);
}
return results;
}
}


I am trying to write a unit test which verifies that when the DynamoDB index returns an ItemCollection then the Dao returns the corresponding results map.



public class DynamoDBDaoTest {

private String key1 = "key1";
private String key2 = "key2";
private String key3 = "key3";
private Long value1 = 1l;
private Long value2 = 2l;
private Long value3 = 3l;

@InjectMocks
private DynamoDBDao dynamoDBDao;

@Mock
private Table table;

@Mock
private Index regionIndex;

@Mock
ItemCollection<QueryOutcome> items;

@Mock
Iterator iterator;

@Mock
private Item item1;

@Mock
private Item item2;

@Mock
private Item item3;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(table.getIndex(DaoDynamo.GSI_REGION_INDEX)).thenReturn(regionIndex);
dynamoDBDao.initialize();

when(item1.getString(anyString())).thenReturn(key1);
when(item1.getLong(anyString())).thenReturn(value1);
when(item2.getString(anyString())).thenReturn(key2);
when(item2.getLong(anyString())).thenReturn(value2);
when(item3.getString(anyString())).thenReturn(key3);
when(item3.getLong(anyString())).thenReturn(value3);
}

@Test
public void shouldReturnResultsMapWhenQueryReturnsItemCollection(){

when(regionIndex.query(anyString(), anyString())).thenReturn(items);
when(items.iterator()).thenReturn(iterator);
when(iterator.hasNext())
.thenReturn(true)
.thenReturn(true)
.thenReturn(true)
.thenReturn(false);
when(iterator.next())
.thenReturn(item1)
.thenReturn(item2)
.thenReturn(item3);

Map<String, Long> results = soaDynamoDbDao.readAll("region");

assertThat(results.size(), is(3));
assertThat(results.get(key1), is(value1));
assertThat(results.get(key2), is(value2));
assertThat(results.get(key3), is(value3));
}
}


My problem is that items.iterator() does not actually return Iterator it returns an IteratorSupport which is a package private class in the DynamoDB document API. This means that I cannot actually mock it as I did above and so I cannot complete the rest of my test.


What can I do in this case? How do I unit test my DAO correctly given this awful package private class in the DynamoDB document API?


Aucun commentaire:

Enregistrer un commentaire