如何使用EasyMock模拟DynamoDB的ItemCollection <queryresult>?

时间:2015-06-22 22:07:18

标签: java amazon-web-services amazon-dynamodb easymock

我有以下Java代码:

Index userNameIndex = userTable.getIndex("userNameIndex");
ItemCollection<QueryOutcome> userItems = userNameIndex.query("userName", userName);

for (Item userItem : userItems) {
}

我正在尝试编写单元测试,我想模仿ItemCollection<QueryOutcome>。问题是ItemCollection<QueryOutcome>::iterator返回的迭代器是IteratorSupport类型,它是一个受包保护的类。因此,无法模拟此迭代器的返回类型。我该怎么做呢?

谢谢!

2 个答案:

答案 0 :(得分:2)

之前的回答是有效的。但是,如果你可以模拟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代码,我会认为他们的代码存在设计缺陷。从公共接口返回包范围类没有意义。它可能应该被提出作为一个问题给他们。

您还可以始终将ItemCollection包装到正确类型的类中:

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();
    }
}

答案 1 :(得分:1)

这可能不是最好的方法,但它可以工作,可能需要你改变你在被测试类中获取迭代器的方式。

@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());

}