2015-06-22 3 views
4

У меня есть следующие Java-код:Как издеваться над ItemCollection DynamoDB <QueryResult> с помощью EasyMock?

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

BTW, я большой поклонник статического импорта, по крайней мере, в тестовом коде. Это делает его более читаемым.

Чтение кода 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

Да. Я знаю. Вы также можете обернуть индекс, чтобы он возвращал реальный ItemCollection вместо класса области пакета. – Henri

Смежные вопросы