Mockito - Stubbing a method of an object that was returned by a mock object method

gsingh2011 picture gsingh2011 · Oct 29, 2011 · Viewed 23.9k times · Source

Let's say I have an mock object, and I don't want to stub any of it's methods, but I want to stub a method of an object it returns. For example,

when(mockObject.method1()).thenReturn(returnValue)

is how it's normally done, but I'm looking for,

when(mockObject.method1().method2()).thenReturn(returnValue)

Is that possible? I get a NullPointerException if I do that. Currently I have stub the first method to return a mock object, and then using that returned mock object, stub the second method. However, these temporary mock objects are useless to me and after chaining many methods together, that results in a lot of useless mock objects.

EDIT: Actually, it's possible that chaining works, but my objects are causing the NPE. This code (the first line) is causing a NPE:

when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

But this code works:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

So chaining didn't work for getNodeAutoIndexer() which returns an AutoIndexer object while it worked for getRelationshipAutoIndexer() which returns a RelationshipAutoIndexer. Both return values are mocked as follows:

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);

So what could be causing the problem?

Answer

JB Nizet picture JB Nizet · Oct 29, 2011

There is no problem at all.

Let's examine these 4 lines of code:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

The first line creates a mock indexManager.

The second one tells the mock graphDb to return indexManager (the mock created at first line) when the index method is called.

The third one telle the mock indexManager (created at first line) to return nodeAutoIndexer when its getNodeAutoIndexer method is called.

And the last line calls graphDb.index(), which returns the mock indexManager (you told it to do that at line two), and asks this indexManager (which is the mock you created at first line) to return relAutoIndexer when its getRelationshipAutoIndexer method is called.

The last line works only because you told the mock graphDb what to return when its index method is called. If you had not done this before, the mock graphDb.index() method would have returned null and you would have had an NPE.