I would like to verify some things using Mockito but studying the documentation has lead me to believe that it's not possible without going outside the usual Mockito tools. Take this for an example:
DrawTool tool = mock(DrawTool.class);
new Drawer().draw(tool);
verify(tool).begin(); // Make sure begin and end are called exactly once each
verify(tool).end();
InOrder inOrder = inOrder(tool);
inOrder.verify(tool).begin();
inOrder.verify(tool).end();
inOrder.verify(tool).flush();
inOrder.verifyNoMoreInteractions();
This test verifies several things well, such as verifying that flush
is the last interaction, but it seems that Mockito has no way to verify that begin
is the first interaction. I'm surprised by that asymmetry in Mockito's tools and so I'm investigating the possibility of creating custom VerificationModes. I'd like to create a VerificationMode called something like beforeAnyOther
and use it like this:
inOrder.verify(tool, beforeAnyOther()).begin();
inOrder.verify(tool).end();
inOrder.verify(tool, beforeAnyOther()).flush();
inOrder.verifyNoMoreInteractions();
The intent would be to verify that begin
is called first and that there are no relevant interactions between end
and flush
while leaving the interactions between begin
and end
unspecified.
I have been studying the source code for the existing VerificationModes and it seems that in principle this should be a simple VerificationMode to implement, but once I get beyond a few of Mockito's major classes the documentation becomes very thin, almost like it's trying to tell me that I shouldn't be touching these classes. I'm especially wary of the packages that start org.mockito.internal
because a name like that suggests to me that these classes are subject to change even though they are public.
The really important classes for implementing a VerificationMode seem to be all in the org.mockito.internal.verification.api
package. That entire package seems to have only one bit of javadoc, and it says, "This package should be open to public once verification API is fully finished." Does that mean that this package is being actively modified and so I shouldn't use anything it contains, or is that just something that it has said for years and the package will probably never actually change?
If I can't use the classes in org.mockito.internal.verification.api
then it seems it is impossible to implement custom VerificationModes. Is there a way to do things like this without custom VerificationModes?
If you can fully specify the sequence of calls that will happen on your mock, then you won't need a beforeAnyOther
verification mode. For example, assuming your desired behavior is...
begin
gets called once, thenend
gets called once, thenflush
gets called oncetool
then the following should the job:
// Verify that the three invocations arrived in the desired order.
InOrder inOrder = inOrder(tool);
inOrder.verify(tool).begin();
inOrder.verify(tool).end();
inOrder.verify(tool).flush();
// Verify that the three invocations are all we received.
Mockito.verify(tool).begin();
Mockito.verify(tool).end();
Mockito.verify(tool).flush();
Mockito.verifyNoMoreInteractions();
On the other hand, if you have any additional calls that happen outside of the sequence you wish to verify then you're correct, Mockito can't verify that at present. So for example, if you knew you had to call tool.setPenColor()
at some point between begin
and flush
but it didn't matter if this call came before or after the call to end
, you'd be out of luck.
You can handle this situation in some other mocking libraries. EasyMock makes this easiest - for example, for a sequence where begin
comes first, flush
comes last, and we don't care about the calls in the middle:
DrawTool mock = EasyMock.createMock(DrawTool.class);
EasyMock.checkOrder(mock, true);
mock.begin();
EasyMock.expectLastCall();
EasyMock.checkOrder(mock, false);
mock.end();
EasyMock.expectLastCall();
EasyMock.expect(mock.someOtherCallThatReturnsAValue()).andReturn(null);
EasyMock.checkOrder(mock, true);
mock.flush();
EasyMock.expectLastCall();
EasyMock.replay(mock);
new Drawer().draw(tool);
EasyMock.verify(mock);
An equivalent test appears to be possible, if unwieldy, in JMock 2. It's a bit easier in JMock 1, but that library is antiquated (circa JDK 1.3), so don't use it. This isn't possible in Moxie (disclaimer/shameless plug: I'm the author), but there's now a todo list item for that.
I can't speak for the Mockito devs as to why the Mockito verification API docs are the way they are - best ask them on the mailing list. I'm sure they'd welcome a patch.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments