javamockitojunit4mongodb-java

Mockito FindIterable<Document>


Am trying to write a JUnit test case for below method, am using Mockito framework.

Method:

public EmplInfo getMetaData(String objectId) {

        objectId = new StringBuffer(objectId).reverse().toString();
        try{
            BasicDBObject whereClauseCondition = getMetaDataWhereClause(objectId);
            EmplInfo emplinfo= new EmplInfo ();
            emplinfo.set_id(objectId);
            FindIterable<Document> cursorPersonDoc = personDocCollection.find(whereClauseCondition);
            for (Document doc : cursorPersonDoc) {
                emplinfo.setEmplFirstName(doc.getString("firstname"));
                emplinfo.setEmplLastName(doc.getString("lastname"));
                break;
            }
            return emplinfo;
        }catch(Exception e){
         e.printstacktrace();
        }

Junit:

@Test
public void testGetMetaData() throws Exception {
    String docObjectId = "f2da8044b29f2e0a35c0a2b5";
    BasicDBObject dbObj = personDocumentRepo.getMetaDataWhereClause(docObjectId);
    FindIterable<Document> findIterable = null;
    Mockito.when(collection.find(dbObj)).thenReturn(findIterable);
    personDocumentRepo.getMetaData(docObjectId);
}

Am getting null point expection in "personDocumentRepo.getMetaData(docObjectId)", because am "Return" the findIterable which is NULL. Not sure how to assign dummy/test value into findIterable.

Please advise.

Thanks! Bharathi


Solution

  • As you have rightly pointed out, you are getting NPE because FindIterable is null. You need to mock it.
    Mocking it is not so straightforward, since it uses MongoCursor(this in turn extend Iterator), you need to mock certain methods which are used internally.

    While traversing certain methods of the Iter

    I believe you have to do something like this.

    FindIterable iterable = mock(FindIterable.class);
    MongoCursor cursor = mock(MongoCursor.class);
    
    Document doc1= //create dummy document;
    Document doc2= //create dummy document;
    
    when(collection.find(dbObj)).thenReturn(iterable);
    
    when(iterable.iterator()).thenReturn(cursor);
    when(cursor.hasNext()) 
      .thenReturn(true)
      .thenReturn(true)// do this as many times as you want your loop to traverse
     .thenReturn(false); // Make sure you return false at the end.
    when(cursor.next())
      .thenReturn(doc1)
      .thenReturn(doc2); 
    

    This is not a complete solution. You need to adapt it to your class.