Last week I wrote about the importance of taking vacation. This time, I have a story to share about an unexpected Mockito limitation.
Consider this example code:
If you want to mock out the ListProvider
in your unit tests, it's pretty simple to do the following:
Where this gets tricky is when you think about providing a mock implementation for ListProvider.currentList
. At first, I thought about just doing this:
whenever(mockListProvider.currentList).thenReturn(listSubject.value)
The problem with this is that if you post a new value to the listSubject
, it will not be reflected in future calls to ListProvider.currentList
because the mock (and by extension, the underlying subject) is evaluated at the time it is defined.
One workaround I came up with was to define a method like this for tests:
Using this instead of the listSubject
directly allows you to update the mock value for currentList
simultaneously.
However, this has some limitations - namely, as a coworker pointed out, it's a little bit messy to re-initialize the mock each time.
Thankfully, Mockito provides another option that's a little bit better suited to this - enter the thenAnswer()
method:
whenever(mockListProvider.currentList).thenAnswer { listSubject.value }
Something to be careful of with this method is that it's not type safe - it would be perfectly valid to write .thenAnswer { 42 }
, and you would only find out when running your tests that you had done something wrong.
One more thing to consider - Mockito isn't the most Kotlin-friendly framework out there, so if the majority of your code is in Kotlin, I would highly encourage you to consider MockK, which lets you write this same code like this:
Do you have any ideas/suggestions for how to further improve on this? Let me know in the comments below! And, please follow me on Medium if you're interested in being notified of future tidbits.
This tidbit was discovered on June 25, 2020.
Top comments (0)