【问题标题】:How to mock DynamoDB's ItemCollection<QueryResult> using EasyMock?如何使用 EasyMock 模拟 DynamoDB 的 ItemCollection<QueryResult>?
【发布时间】:2015-06-22 22:07:17
【问题描述】:

我有以下 Java 代码:

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

for (Item userItem : userItems) {
}

我正在尝试编写一个单元测试,我想模拟ItemCollection&lt;QueryOutcome&gt;。问题是ItemCollection&lt;QueryOutcome&gt;::iterator 返回的迭代器是IteratorSupport 类型,这是一个包保护类。因此,不可能模拟这个迭代器的返回类型。我能做些什么呢?

谢谢!

【问题讨论】:

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


    【解决方案1】:

    前面的答案是有效的。但是,如果您可以模拟 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();
        }
    }
    

    【讨论】:

    • 您的回答非常好,但是,当然,ItemCollection 是从 Dynamo 客户端返回的,因此很难使用它。
    • 是的。我知道。您还可以包装 Index 让它返回一个真正的 ItemCollection 而不是包范围类。
    • 很好的答案!我已经使用 Mockk 库在 Kotlin 中成功实现了您的解决方案。谢谢兄弟!
    【解决方案2】:

    这可能不是最好的方法,但它确实有效,并且可能需要您更改在被测类中获取迭代器的方式。

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

    【讨论】:

    • 只是想注意IteratorSupport 不再打包保护,因此可以直接模拟。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多