verifyNoMoreInteractions and stubbed calls

475 views
Skip to first unread message

Stephen Duncan Jr

unread,
Sep 11, 2009, 10:38:04 AM9/11/09
to moc...@googlegroups.com
I frequently find cases where I want to use verifyNoMoreInteractions, but my tests would fail because of calls to my stubbed methods.  Sure, I could add explicit verify calls for those, but that ends up looking very repetitive.  I think I could use (either or both): a version of verifyNoMoreInteractions that counted stubbed calls the same as verified calls (not sure what the API would look like to differentiate), and/or verifyNoMoreInteractions(this.mock).myMethodIDoNotWantCalledAgain() (could also go with verify(this.mock, noMoreCalls()).myMethodIDoNotWantCalledAgain()). 

Thoughts?

--
Stephen Duncan Jr
www.stephenduncanjr.com

Johan Haleby

unread,
Sep 11, 2009, 1:00:34 PM9/11/09
to moc...@googlegroups.com
I'm thinking about implementing this for the Mockito extension in PowerMock for version 1.3 so I'm also interested to know what people think about it.

szczepiq

unread,
Sep 12, 2009, 1:15:02 PM9/12/09
to moc...@googlegroups.com
Hi,

> I'm thinking about implementing this for the Mockito extension in PowerMock

Up to you ;)

>> I frequently find cases where I want to use verifyNoMoreInteractions, but

I don't think verifyNoMoreInteractions should be used frequently. It
overspecifies tests and makes them brittle. Also, one does not have to
pass all collaborators to verifyNoMoreInteractions() - just pass the
collaborators that really require strict verification (stubs usually
don't). The only problem is when the very same collaborator plays
multiple roles: you ask him for data in one interaction, you tell him
to do something in different interaction. However, usually it's a sign
of poor design. To recap: it feels the problem is elsewhere - either
in overusing of verifyNoMoreInteractions() or in poor design. I'm keen
on seeing some real code that demonstrates the need for this feature.

OTOH verifyNoMoreInteractions() might be useful for legacy code.

>> also go with verify(this.mock,
>> noMoreCalls()).myMethodIDoNotWantCalledAgain()).

I might be missing something but I don't understand this feature. Why
cannot I use verify(this.mock,
never()).myMethodIDoNotWantCalledAgain() or explicit:
verify(this.mock, times(2)).....

Cheers,
Szczepan Faber

Stephen Duncan Jr

unread,
Sep 12, 2009, 3:33:14 PM9/12/09
to moc...@googlegroups.com
On Sat, Sep 12, 2009 at 1:15 PM, szczepiq <szcz...@gmail.com> wrote:

>> I frequently find cases where I want to use verifyNoMoreInteractions, but

I don't think verifyNoMoreInteractions should be used frequently. It
overspecifies tests and makes them brittle. Also, one does not have to
pass all collaborators to verifyNoMoreInteractions() - just pass the
collaborators that really require strict verification (stubs usually
don't). The only problem is when the very same collaborator plays
multiple roles: you ask him for data in one interaction, you tell him
to do something in different interaction. However, usually it's a sign
of poor design. To recap: it feels the problem is elsewhere - either
in overusing of verifyNoMoreInteractions() or in poor design. I'm keen
on seeing some real code that demonstrates the need for this feature.

OTOH verifyNoMoreInteractions() might be useful for legacy code.


Frequently was a relative term.  I've tried to take your advice to heart, and I do not use verifyNoMoreInteractions on every call.  I do try to limit it to when I think it's really part of what I want so specify.  So most of our tests don't use it; I more meant that, when I use the feature, it frequently comes up that I have to add extraneous verify calls to my stubbed methods.

 
>> also go with verify(this.mock,
>> noMoreCalls()).myMethodIDoNotWantCalledAgain()).

I might be missing something but I don't understand this feature. Why
cannot I use verify(this.mock,
never()).myMethodIDoNotWantCalledAgain() or explicit:
verify(this.mock, times(2)).....

Cheers,
Szczepan Faber


I'll try to take a stab at describing the real scenario without access to that code at the moment.

The test is trying to verify that a method iterates over some data, processes it, and then checks the items back in that it processed.  We want to verify also that it doesn't try to check in anything additional.  So we have something like:

when(service.checkout()).thenReturn(docs(1,2)).thenReturn(docs(3,4));

process();

verify(service).checkIn(docs(1, 2));
verify(service).checkIn(docs(3,4));

// Somehow verify no other calls to checkIn...

If I do verify(service, never()).checkIn(any(Collection.class)), then it fails because of the verify calls.  If I do verifyNoMoreInteractions for the service, then the stubbed checkout methods cause it fail. 

As far as I can tell, the only way to get Mockito to do what I want currently is to add verify calls for every stubbed method and use verifyNoMoreInteractions, hence the proposed new techniques.  If there's another way to use the existing calls to solve this sceneario, I'd be happy to do so.

szczepiq

unread,
Sep 12, 2009, 4:01:11 PM9/12/09
to moc...@googlegroups.com
> when(service.checkout()).thenReturn(docs(1,2)).thenReturn(docs(3,4));

Oh, got it ;)

I think there is a way of doing it with the current api.

InOrder inOrder = inOrder(service);
inOrder.verify(service).checkIn(docs(1, 2));
inOrder.verify(service).checkIn(docs(3,4));
inOrder.verify(service, never()).checkIn(docs(anyInt(), anyInt()));

I don't suggest the above because it's clearly a workaround.

I think this sort of api makes sense:

verify(service, noMoreInvocations()).checkIn(docs(anyInt(), anyInt()));

Have a stab at the implementation (should not be difficult) and get
back with a patch :)

Cheers,
Szczepan Faber
Reply all
Reply to author
Forward
0 new messages