How to verify a method call on a dependency

Guest post by Lior Friedman.

Interaction testing is a common type of unit testing. In this type of tests, one checks that a specific unit “interacts” with another way according to an agreed protocol, usually this protocol is embodied in the used class API. Its in interaction tests that mocking framework becomes real handy.

Let’s do an example.

I have a system, which tracks my schedule. It publishes a certain API that enable to ask me to do things. However,internally it works asynchronously. When it receives a request, it verifies that it can handle the request. If this condition is met, it issues a request on a message queue in order to switch the execution content (and handle the details with the request).

In order to keep the example simple I’ll ignore the need to return an answer from the requested execution.

Here’s a simple example of such an API method:

public bool PickKidsFromSchool(DateTime onDate)
{
if (TooFarInThFuture(onDate))
{
return false;
}
if (!Free(onDate)
&& CantMoveAppointments(onDate) )
{
return false;
}
var request = new PickKidsRequest(onDate);
_RequestQueue.Enqueue(request);
return true;
}

And here’s the logic in charge of the actual handling of the message:

public void HandleRequest(MySchedule Scheduler)
{
Scheduler.FreeTime(
SCHOOL_END_TIME,
MySchedule.Evening);

Appointment appointment =
new Appointment("Pick kids");

Scheduler.SetAppointment(
appointment,
_RequestDate,
SCHOOL_END_TIME);
}

There are several ways to tackle testing of such a component. My preferred way is to split the problem into two main parts (and a smaller hidden one) and test each part separately: The first part is to test the handling logic (HandleRequest) , i.e. after the message was taken from the queue. The second part is to test API method (PickKidsFromSchool), making sure it  does the proper verification, and at the end issue “enqueue” the proper message on the queue. We’re not going to talk about those today.

The “hidden” part is to verify that the queuing mechanism itself is working properly.  Specifically, we need to make sure we’re able to pass a message to and from the queue to the appropriate handler.

Here’s how I use Isolator in order to verify specific calls, and how it allows me to test the second part.

Here is the test:

[TestMethod()]
[Isolated]
public void PickKids_HasTime_EnqueRequest()
{
var fakeQueue =
Isolate.Fake.Instance<Queue<Requests>>();
DateTime onDate = new DateTime(2010, 8, 10);

var target = new MySchedule(fakeQueue);
target.PickKidsFromSchool(onDate);

var expectedRequest =
new PickKidsRequest(onDate);
Isolate.Verify.WasCalledWithExactArguments
(() => fakeQueue.Enqueue(expectedRequest));

}

The interesting line is the last line of the test:

Isolate.Verify.WasCalledWithExactArguments
(() => fakeQueue.Enqueue(expectedRequest));

This statement verifies that a message was sent to the queue, and also verifies that the sent message matches the expected message supplied. The test fails if neither of these conditions are met.

Similarly I can use the following statement to verify that a message was not queued, which is necessary to test cases that reject the request.

Isolate.Verify.WasNotCalled
(() => fakeQueue.Enqueue(null));

In conclusion: because our code interacts with other pieces, we need to know it calls them, and does so correctly. With Verify it’s easy to set the pass/fail criterion for interaction, and make sure the correct call on the dependency was made.

Lior Friedman

TOP