2015-06-22 60 views
4

我有以下的Java代碼:如何使用EasyMock模擬DynamoDB的ItemCollection <QueryResult>?

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

for (Item userItem : userItems) { 
} 

我試圖寫一個單元測試,我想嘲笑ItemCollection<QueryOutcome>。問題是由ItemCollection<QueryOutcome>::iterator返回的迭代器類型爲IteratorSupport,它是一個包保護類。因此,嘲笑這個迭代器的返回類型是不可能的。我能做些什麼呢?

謝謝!

回答

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

} 
+0

只是想指出,'IteratorSupport'不再打包保護,所以它可以直接嘲笑。 – Max

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

您的回答非常好,但是,當然,ItemCollection是從Dynamo客戶端返回的內容,因此很難避免使用它。 – Max

+0

是的。我知道。你也可以包裝Index來讓它返回一個真正的ItemCollection,而不是包範圍類。 – Henri

相關問題