Ich habe das folgende einfache DynamoDBDao, die eine Methode enthält, die einen Index abfragt und eine Zuordnung der Ergebnisse zurückgibt.Mockito: Mocking-Paket private Klassen
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;
}
}
Ich versuche, eine Unit-Test zu schreiben, dass überprüft, wenn der DynamoDB Index eine ItemCollection kehrt dann das Dao die entsprechenden Ergebnisse Karte zurückgibt.
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));
}
}
Mein Problem ist, dass items.iterator() tatsächlich Iterator nicht zurückgibt es eine IteratorSupport gibt, die ein Paket private Klasse in der DynamoDB Dokument API ist. Dies bedeutet, dass ich es nicht so verspotten kann wie ich es oben getan habe und deshalb kann ich den Rest meines Tests nicht abschließen.
Was kann ich in diesem Fall tun? Wie kann ich mein DAO richtig testen, wenn ich diese schreckliche private Paketklasse in der DynamoDB-Dokument-API verwende?
Implementierungsdetails wie Sichtbarkeit sind einer der Gründe für die Richtlinie „[nicht Scheintypen, die Sie nicht besitzen] (http : //www.davesquared.net/2011/04/dont-mock-types-you-dont-own.html) ". Können Sie eine Abstraktion über eines dieser Objekte mit einem Vertrag/einer Implementierung schreiben, die Sie steuern, oder stattdessen mit einer Schnittstelle codieren? –
Hallo Jeff, danke für deinen Kommentar. Ich sehe nicht, wie ich mit einem Vertrag/einer Implementierung, die ich kontrolliere, eine Abstraktion über diese Objekte schreiben kann. Ich habe mein aktuelles Toolset, das durch meine Kenntnisse und Erfahrungen begrenzt ist, erschöpft. Kannst du etwas sehen, was ich derzeit nicht kann? Wenn ja, wäre ich dankbar, wenn Sie mich in die richtige Richtung weisen könnten. –