Sometimes I miss the forest for the trees – and that for a disturbingly long time. I just became aware of this once again recently, typing one of the more verbose mockito expressions for the umpteenth time. The statement in question was a
doAnswer(Answer) construct which always feels a bit cumbersome to code with the static import and generics stuff involved.
Although I am using Eclipse java templates regularly to generate e.g. loop, switch and other constructs it took me a couple of years (only…) to come up with the idea of writing a few of them by myself for the mockito expressions I use daily. Not very surprisingly it turned out that this streamlined my work a bit. So I thought it might be a good idea to share a github gist for people who are interested.
I will not go over all templates in detail but shortly explain the concept on the basis of the
ArgumentCapture construct. With the latter I almost always ran into the problem that using camel case typing combined with auto completion automatically adds a type argument which I had to remove manually afterwards:1.
Using java templates circumvents the problem as you only have to type the first letters of a template’s name and select it from the content assist’s drop down. The complete code construct is generated and the only thing you have to do is fill out the variables2:
Basically you work your way through the generated construct using tabs. As shown in the image below the first template-variable is marked and ready for editing. Variables with the same name belong together and will be changed synchronously (see the generic type-/classname-variable in the picture). Once you are done with the current variable use the ‘tab’ key to mark the next one. And once you are finished with the whole construct press ‘enter’ to jump to the green vertical line described in the image as cursor position.
Note that the template also handles import and static import if needed. Eventually you will end up with something looking like the first line of the following testing method excerpt:
ArgumentCapture construct is not very large I really appreciate having a template for it now. The fastest way of typing I could come up with (using content assist, assign to local variable with CRTL+1 etc.) needs seven steps, while the approach described here does the same in four steps34.
The last example image shows what the generated expression for the more verbose
doAnswer(Answer) construct mentioned in the introduction will look like:
For the sake of completeness I conclude this post with a list of the templates that are available in the gist5:
|Mockito doAnswer(answer).when(mock).call() construct
|Mockito doAnswer(answer).when(mock).call() construct that manipulates invocation argument
|Mockito doReturn(value).when(mock).call() construct
|Mockito doThrow(throwable).when(mock).call() construct
|Mockito ArgumentCaptor.forClass(Type.class) construct
|Mockito when(mock.call()).thenAnswer(answer) construct
|Mockito when(mock.call()).thenAnswer(answer) construct that manipulates invocation argument
|Mockito when(mock.call()).thenReturn(value) construct
|Mockito when(mock.call()).thenThrow(throwable) construct
- Github Gist Download: https://gist.github.com/fappel/8863588
If you have any ideas for additional mockito templates, improvements, criticism, alternatives or the like I would of course be glad to here about it. So don’t be shy, give it a try!
- Well, one could work around that using favorites and static imports like my dear fellow Holger Staudacher describes in his post about using mockito effectively. However for unexplainable reasons I did not get this into my fingers with
- ‘forClass’ might not be the most resourceful name, but everyone is free to choose a better one though !
- Note that with ‘step’ I do not mean key stroke. Depending on your environment the actual amounts of keystrokes may vary. Besides I will not provide a precise definition of the term step – I leave it up to you to make your own comparison
- Aside from the actual step count, it seems to me that the template approach consumes less brainpower, but that might be completely a personal delusion
- Improvement suggestions for names and descriptions are highly appreciated