search the lab

Embedded Testing with Unity & CMock (by Mark)

Embedded Testing with Unity & CMock

James Grenning's book (features Unity)

Test Driven Development for Embedded C

Topics

Entries in mocking (1)

Sunday
Mar132011

Basic Mocking with CMock

Once you understand how basic unit testing with Unity works, you're ready to understand how CMock can be added to make it extra-powerful.

For each test, one (or more rarely multiple) real module is linked with mock versions of any other modules that it interacts with. These are tested against a test file. Then, another module is tested, bringing in the mocks of files that IT interacts with, and using the real version of it. This continues until all real modules have been tested, and very likely the mock versions of many of them have been used to help.

Here's a pretty picture that helps describe that:

So what are mocks for? Well, they simplify your unit test-writing by allowing you complete control over nearby modules without you have to write a bunch of stubs yourself. They do a number of things for you.

They're Call-Verifiers and Return-Value-Injectors

Let's say you have a function called OpenBarrel. When you call OpenBarrel, it checks for up to five possible monkeys that might be in the Barrel by calling CheckForMonkey(). If the monkey is there, it calls JumpMonkey() so that monkey can leap out joyfully! Let's say OpenBarrel is in Barrel.c and the other two functions are in Monkey.c. We might have a test that looks like this, then:

TestBarrel.c:

#include "unity.h"
#include "cmock.h"
#include "Barrel.h"
#include "MockMonkey.h"

void test_PlayWithMyBarrelOfMonkies(void)
{
    CheckForMonkey_ExpectAndReturn(1); 
    JumpMonkey_Expect();
    CheckForMonkey_ExpectAndReturn(1); 
    JumpMonkey_Expect();
    CheckForMonkey_ExpectAndReturn(0); 

    OpenBarrel();
}

So CMock uses Monkey.h to generate MockMonkey.c and MockMonkey.h. These include mock versions of the original functions, as well as handy helper functions which are used to tell the system what you expect to happen. Then, when you build TestBarrel's executable, you link in this mock version instead of the real Monkey module. See how it's suddenly easier to test Barrel.c? This required no changes to Barrel.c itself... and it didn't require you to hand-create anything for the mocks... you just get auto-generated goodness that you can start to use.

They're Argument-Verifiers

It's kinda hard to check what's going on inside a function sometimes... especially if that function doesn't have any arguments or return values of its own. With mocks, though, this is a piece of cake. When you set up your expectations, you're stating what you expect to get passed.

Let's say I want to peek in the barrel. The first time I want to just check for a crazy monkey by calling CheckForMonkeys(bool crazy_only). The next time I want to check for any monkeys... Then I check for the crazy one again.

TestBarrel.c:

#include "unity.h"
#include "cmock.h"
#include "Barrel.h"
#include "MockMonkey.h"

void test_PeekAtMyMonkeys(void)
{
    CheckForMonkeys_Expect(1);
    CheckForMonkeys_Expect(0);
    CheckForMonkeys_Expect(1);

    PeekInBarrel();
}

Nice, eh? And you can do that for all sorts of arguments... arrays, strings, pointers, structs, numbers... some of those things get a little more complicated, but we're discussing the basics right now, right?

That seems like enough for a basic mocking lesson. There will definitely be more later!

More Mocking Topics