Monday, February 27, 2012

The Many Faces of Midje Fakes

The Midje Clojure testing library enables top-down development, and the primary tool it has for enabling it is the fake.

In Midje, you don't have mock objects like you do in object-oriented languages, instead you fake out functions. The simplest way you can fake out functions is by using the provided form within your fact.

Fakes

(Things that look like ..x.. are called Midje metaconstants. For now just pretend they are constants, or skip to the end of this article for a link to the wiki.)

In the above example we've managed to define six-times in terms of a function, doubler, that is not yet defined (it is unfinished).

Presumably the next thing we'd do when designing a piece of software like this is to write the fact for doubler.
Or perhaps write a more thorough test:
(Tabular is a way to write one fact that runs against multiple input sets.)

The Myriad Uses of Fakes


Fakes have other uses besides simple stubbing.

They can also be used to verify call counts. Imagine that you want to check that when some data is not valid there are no calls to send-email, but otherwise there will be 1 call sent to each recipient?

We can write this kind of test using the :times n prerequisite option. (where n is some non-negative integer)

Checkers


Using checkers we can even expand on the idea of what can be checked by a provided. In the above examples first we used the anything checker to check that the email function was never called with anything. Then we simply checked that the email function was called with :alex and :brian once each.

In this example we want to check that the query function is called with 10 things that look like query maps. To do that we first need to create our own checker that checks whether the parameter looks like a query.
Midje will say that any arg matches this checker if it has a non-false/non-nil :target-db and :query-plan.

Let's confirm query is called 10 times with params that look like queries.

The Fake Chain Gang


If you've ever violated The Law of Demeter in an object-oriented language and then tried to use mock objects with the offending class, you may have experienced a chain of mocks.

A chain of mocks is when you mock a method on a mock object that itself returns another mock object, that has a method on it mocked to *finally* return the value you want.

when(mockA.call()).thenReturn(mockB);
when(mockB.call()).thenReturn(mockC);
when(mockC.call()).thenReturn(42);

In Midje the naive approach might be to write something like:
Midje supplies a feature called Folded Prerequisites that enable a nice condensed syntax for this, though it is probably a code smell if you are doing this too often.

Fakes That Cover Multiple Facts


There are other ways to make fakes in Midje as well, by using the background macro and the against-background macros. These give you the ability to write fakes that cover a group of fakes. I think I'll talk about them in another blog though time permitting.

Wiki Links

Metaconstants
Using Checkers in Fakes
Folded Prerequisites

1 comment:

  1. Hey, saw your write ups. It is quite interesting. Please share your profile at hema.powar@wipro.com if you are looking for job. We have projects for a reputed client in Cupertino CA. Think you might have guessed the client already :-)

    Reach out to me at 201-272-6303

    ReplyDelete