如何使用 EasyMock 模拟 DynamoDB 的 ItemCollection<QueryResult>?
How to mock DynamoDB's ItemCollection<QueryResult> using EasyMock?
我有以下 Java 代码:
Index userNameIndex = userTable.getIndex("userNameIndex");
ItemCollection<QueryOutcome> userItems = userNameIndex.query("userName", userName);
for (Item userItem : userItems) {
}
我正在尝试编写单元测试,我想模拟 ItemCollection<QueryOutcome>
。问题是 ItemCollection<QueryOutcome>::iterator
编辑的迭代器 return 是类型 IteratorSupport
,它是一个受保护的包 class。因此,不可能模拟此迭代器的 return 类型。我可以做什么?
谢谢!
这可能不是最好的方法,但它可以工作,并且可能需要您更改在 class 测试中获取迭代器的方式。
@Test
public void doStuff() throws ClassNotFoundException {
Index mockIndex;
ItemCollection<String> mockItemCollection;
Item mockItem = new Item().with("attributeName", "Hello World");
mockItemCollection = EasyMock.createMock(ItemCollection.class);
Class<?> itemSupportClasss = Class.forName("com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport");
Iterator<Item> mockIterator = (Iterator<Item>) EasyMock.createMock(itemSupportClasss);
EasyMock.expect(((Iterable)mockItemCollection).iterator()).andReturn(mockIterator);
EasyMock.expect(mockIterator.hasNext()).andReturn(true);
EasyMock.expect(mockIterator.next()).andReturn(mockItem);
EasyMock.replay(mockItemCollection, mockIterator);
/* Need to cast item collection into an Iterable<T> in
class under test, prior to calling iterator. */
Iterator<Item> Y = ((Iterable)mockItemCollection).iterator();
Assert.assertSame(mockItem, Y.next());
}
之前的回答有效。但是,如果您可以模拟 Iterable 而不是 ItemCollection,您的生活将会更轻松。
Iterable<Item> mockItemCollection = createMock(Iterable.class);
Iterator<Item> mockIterator = createMock(Iterator.class);
Item mockItem = new Item().with("attributeName", "Hello World");
expect(mockItemCollection.iterator()).andReturn(mockIterator);
expect(mockIterator.hasNext()).andReturn(true).andReturn(false);
expect(mockIterator.next()).andReturn(mockItem);
replay(mockItemCollection, mockIterator);
for(Item i : mockItemCollection) {
assertSame(i, mockItem);
}
verify(mockItemCollection, mockIterator);
顺便说一句,至少在测试代码中,我是静态导入的忠实拥护者。它使它更具可读性。
阅读AWS代码,我会认为他们的代码存在设计缺陷。从 public 接口 return 包范围 class 没有意义。这可能是应该向他们提出的问题。
您也可以始终将 ItemCollection 包装成正确类型的 class:
public class ItemCollectionWrapper<R> implements Iterable<Item> {
private ItemCollection<R> wrapped;
public ItemCollectionWrapper(ItemCollection<R> wrapped) {
this.wrapped = wrapped;
}
public Iterator<Item> iterator() {
return wrapped.iterator();
}
}
我有以下 Java 代码:
Index userNameIndex = userTable.getIndex("userNameIndex");
ItemCollection<QueryOutcome> userItems = userNameIndex.query("userName", userName);
for (Item userItem : userItems) {
}
我正在尝试编写单元测试,我想模拟 ItemCollection<QueryOutcome>
。问题是 ItemCollection<QueryOutcome>::iterator
编辑的迭代器 return 是类型 IteratorSupport
,它是一个受保护的包 class。因此,不可能模拟此迭代器的 return 类型。我可以做什么?
谢谢!
这可能不是最好的方法,但它可以工作,并且可能需要您更改在 class 测试中获取迭代器的方式。
@Test
public void doStuff() throws ClassNotFoundException {
Index mockIndex;
ItemCollection<String> mockItemCollection;
Item mockItem = new Item().with("attributeName", "Hello World");
mockItemCollection = EasyMock.createMock(ItemCollection.class);
Class<?> itemSupportClasss = Class.forName("com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport");
Iterator<Item> mockIterator = (Iterator<Item>) EasyMock.createMock(itemSupportClasss);
EasyMock.expect(((Iterable)mockItemCollection).iterator()).andReturn(mockIterator);
EasyMock.expect(mockIterator.hasNext()).andReturn(true);
EasyMock.expect(mockIterator.next()).andReturn(mockItem);
EasyMock.replay(mockItemCollection, mockIterator);
/* Need to cast item collection into an Iterable<T> in
class under test, prior to calling iterator. */
Iterator<Item> Y = ((Iterable)mockItemCollection).iterator();
Assert.assertSame(mockItem, Y.next());
}
之前的回答有效。但是,如果您可以模拟 Iterable 而不是 ItemCollection,您的生活将会更轻松。
Iterable<Item> mockItemCollection = createMock(Iterable.class);
Iterator<Item> mockIterator = createMock(Iterator.class);
Item mockItem = new Item().with("attributeName", "Hello World");
expect(mockItemCollection.iterator()).andReturn(mockIterator);
expect(mockIterator.hasNext()).andReturn(true).andReturn(false);
expect(mockIterator.next()).andReturn(mockItem);
replay(mockItemCollection, mockIterator);
for(Item i : mockItemCollection) {
assertSame(i, mockItem);
}
verify(mockItemCollection, mockIterator);
顺便说一句,至少在测试代码中,我是静态导入的忠实拥护者。它使它更具可读性。
阅读AWS代码,我会认为他们的代码存在设计缺陷。从 public 接口 return 包范围 class 没有意义。这可能是应该向他们提出的问题。
您也可以始终将 ItemCollection 包装成正确类型的 class:
public class ItemCollectionWrapper<R> implements Iterable<Item> {
private ItemCollection<R> wrapped;
public ItemCollectionWrapper(ItemCollection<R> wrapped) {
this.wrapped = wrapped;
}
public Iterator<Item> iterator() {
return wrapped.iterator();
}
}