Mocking fakes or faking mocks

Mocks or fakes?

The eternal question or, if you are a strongly opinionated person like me, not really a question at all. The answer is simple right?

Mocks for verifying side effects, fakes for programmable behaviour.

What I mean by that is that I always held a very stong view that you should ONLY use mocks for verifying that your code called a method as a result of some testable operation, NOT to seed data or state into your test. An example from an old colleague that stuck with me is this:

Use a mock to verify your method called something like facebookService.logOut(). Use a fake to create an arrangment that says your user is logged in to Facebook like so: facebookFake.userIsLoggedIn()
Paraphrasing @tddmonkey

I’ve always been quite opposed to the obsession our mobile dev community seems to have embraced mocking libraries like Mockito/MockK with. It has led, in my humble opinion, to the proliferation of very ugly test code, using mocks to set up state or feed data to our code, increasing duplication massively and reducing maintainability.

Encapsulate behaviour! I would often shout late at night waking up from nightmares of bad test code.

This:

every { service.getAddress() } returnsValue { testAddress }

Is a how , not a what. Write this instead:

fakeService.returnsAddress(testAddress)

The how of how an address is returned (in this case as a return value of a method call) is encapsulated in the fake, reducing duplication and, as a side effect, making it so that if in the future you wish to change the API of your service to, say, a Flow of addresses, you only have to change the implementation in one place, not touching your tests.

Amazing advise if I say so myself. What an excellent mentor you are Savvas (self pat on my back). The ‘problem’ is that people love their mocks cause it saves them from implementing fakes.

Why do I have to create a whole new class and implement some sort of internal data structure to keep the address and return it when I can use a one liner from Mockito/MockK? Also, the error messaging is nicer there. I will need to implement good error messages too now!
Lazy developer

Developers are SOOO lazy πŸ™„ I would say to myself.
Don’t they know that you have to make sacrifices for code quality?!?

Until I rememebered. Wait a minute. I’m a lazy developer too!

Kotlin to the rescue!

Kotlin allows us to write beautiful, encapsulated, code without the need to create custom classes, gaining the benefits of fakes, without the overhead of creating them ourselves and getting Mockito/MockK’s nice error messages.

Enter extension functions

For the above example, we can write:

// FakeService.kt

fun Service.returnsAddress(address: Address) =
  every { service.getAddress() } returnsValue { address }

Boom! Now we have the best of both worlds. Encapsulation of the ‘how‘ in one method that can be centrally modified if the API contract changes (thus not needing to modify any tests), plus the benefit of not needing to write a new class for our fake and implement it with the addition of Mockito/MockK’s nice error messages.

I can now say I’m a convert (caveats apply). I love mocking frameworks too!