How do I mock adding to a list inside iterator like the code below? I want to add to the list because my method returns List and I want to do an assert on that but not sure how to add my object to the list inside the iterator? Or am I misunderstanding and the mocking should occur in the Util.jsonToObject
?
public List<Users> getUsers(String userId) {
List<Users> usersList = new ArrayList<>();
Table table = dynamoDB.getTable("users");
ItemCollection<QueryOutcome> items = table.getIndex("userIndex").query(QuerySpec);
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
list.add(Util.jsonToObject(iterator.next().toJSONPretty(), Users.class));
}
return usersList;
}
Here is the test
List<Users> mockList = mock(ArrayList.class);
Users details = new Users("1", UUID.randomUUID().toString(), null, "");
List<Users> usersList = new ArrayList<>();
usersList.add(details);
Table mockTable = mock(Table.class);
Item item = mock(Item.class);
mockTable.putItem(item);
Index mockIndex = mock(Index.class);
ItemCollection<QueryOutcome> mockCollection = mock(ItemCollection.class);
Item mockItem = mock(Item.class);
IteratorSupport<Item, QueryOutcome> mockIterator = mock(IteratorSupport.class);
when(dynamoDB.getTable("users")).thenReturn(mockTable);
when(mockTable.getIndex(anyString())).thenReturn(mockIndex);
when(mockIndex.query(any(QuerySpec.class))).thenReturn(mockCollection);
when(mockCollection.iterator()).thenReturn(mockIterator);
when(mockIterator.hasNext()).thenReturn(true).thenReturn(false);
doReturn(true).when(mockList).add(details);
when(mockIterator.next()).thenReturn(mockItem);
when(mockItem.toJSONPretty()).thenReturn("");
assertSame(dynamoDBService.getUsers("").get(0), usersList);
Unsolicited Suggestion 1: Learn how to use the Mockito annotations, they make everything easier to do and easier to read.
Unsolicited Suggestion 2:
Use doReturn().when()
instead of when().thenReturn()
.
Try a google search for "is doReturn better than thenReturn" for discussion.
Suggested Answer:
Don't instantiate a new User class mock object in the subbing of the
list.add
method.
Instead,
match any instance of the User class.
Here is some example code:
@ExtendWith(MockitoExtension.clss)
public class TestBlam
{
private static final String VALUE_PRETTY_JSON = "{}";
private Blam classToTest; // Blam is the class that you are actually testing.
@Mock
private ItemCollection<QueryOutcome> mockCollection;
@Mock
private Item mockItem;
@Mock
private IteratorSupport<Item, QueryOutcome> mockIterator;
@BeforeEach
void beforeEach()
{
// instantiate the thing that you will actually test.
classToTest = new Blam();
}
@Test
void blamTest()
{
doReturn(mockIterator).when(mockCollection).iterator();
doReturn(true).doReturn(false).when(Iterator).hasNext();
// The answer to your question is the next line.
doReturn(true).when(mockList).add(any(User.class));
doReturn(mockItem).when(mockIterator).next();
doReturn(VALUE_PRETTY_JSON).when(mockItem).toJSONPretty();
// perform the test. ...
}
}