CMock

Automated Mock & Stub Generation For C

C

CMock generates pure C code from regular C headers. No special markup required.

Expectations

Use CMock to specify what functions your tests Expect to be called, and what arguments you expect them to be called with.

Ignores

If some function calls aren't important for this test, tell CMock to ignore calls to them, or just ignore the details.

Callbacks

Sometimes you want more control of the situation. No problem, tell CMock to call your own custom functions to do whatever needs to be done.

Custom Types

CMock handles all built in types. WIth just a little help, it can handle any of your custom types as well.

Automatic

CMock automatically generates your mock modules from simple headers, saving you from tediously creating your own stubs.

Chalkboard_by_DallasKrentzel.jpg

HOW CMOCK WORKS

CMock creates mocks and stubs for C functions. It's useful for interaction-based unit testing, where you want to test how one module interacts with other modules. Instead of trying to compile all those real units together, CMock helps you by creating fake versions of all the "other" modules. You can then use those fake versions to verify that your module is working properly!

CMock uses Ruby scripts to auto-generate C source modules conforming to the interfaces specified in your C header files. It searches your header files for function declarations. For example, you might tell it to look in your NeatStuff.h file, where it sees the following:


int ParseStuff(char* Cmd);
void HandleNeatFeatures(NEAT_FEATURE_T NeatFeature);

CMock takes those function declarations, and it creates a set of Mock objects and helpers (which are put in a new C and header file called MockNeatStuff.c and MockNeatStuff.h):


int ParseStuff(char* Cmd);
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);
void ParseStuff_IgnoreAndReturn(int toReturn);
void ParseStuff_StubAndCallback(CMOCK_ParseStuff_CALLBACK Callback);

void HandleNeatFeatures(NEAT_FEATURE_T* NeatFeature);
void HandleNeatFeatures_Expect(NEAT_FEATURE_T* NeatFeature);
void HandleNeatFeatures_ExpectWithArrays(NEAT_FEATURE_T* NeatFeature, int NeatFeature_Depth);
void HandleNeatFeatures_Ignore(void);
void HandleNeatFeatures_StubAndCallback(CMOCK_HandleNeatFeatures_CALLBACK Callback);

Now that you have these new functions, what do you do with them? You can use to help write tests for modules that call functions in NeatStuff.h. For example, this contrived example:


int MyFunc(char* Command)
{
  int ID;
  NEAT_FEATURES_T Neat;
 
  ID = ParseStuff(Command);
  switch(ID) 
  {
  case 0: 
    HandleStupidFeatures();
    return 1;

  case 1:
    Neat.id = 1;
    Neat.cmd = Command;
    HandleNeatFeatures(Neat);
    return 1;

  default:
    return 0;
  }
}

So, how does that work? How do we write tests using our new Mocked versions? Well, you write a normal-looking Unity test. Before the function under test is called, you can call one or more Expectations. These state what mocked functions you are expecting to be called. You can even specify what arguments you expect to see, AND tell them what data to return. The latter feature is super helpful for injecting data into your functions to verify that they will handle it correctly. It looks something like this:


void test_MyFunc_should_ParseStuffAndCallTheHandlerForNeatFeatures(void)
{
  int retval;

  //We start by saying what our expectations are, and what we want to return
  NEAT_FEATURES_T ExpectedFeatures = { 1, "NeatStuff" };
  ParseStuff_ExpectAndReturn("NeatStuff", 1);
  HandleNeatFeatures_Expect(ExpectedFeatures);

  //Run Actual Function Under Test
  retval = MyFunc("NeatStuff");

  //We can still verify whatever things we normally would after
  TEST_ASSERT_EQUAL(1, retval);
}

In this case, our silly little test passes. If we had instead returned 0 as our ID when ParseStuff_ExpectAndReturn was called, we would be able to verify that HandleStupidFeatures is called instead. Whenever CMock comes across a mismatch in what was called versus what was expected, it gives us a helpful Unity failure, like:


MyFunc.c:23:test_MyFunc_should_ParseStuffAndCallHandler2:FAIL:Function 'HandleStupidFeatures' called less times than expected.

or


MyFunc.c:23:test_MyFunc_should_DoOtherStuff:FAIL:Function 'ParseStuff' Argument 'Cmd' Expected 'NeatStuff' was 'DumbStuff'

The best part is that all of that plumbing was put in with almost no effort on your part. You just had to point CMock at the header files of the modules that your module interacts with! Clearly, this puts a bit more work on your build system, but once it's in place, you're able to do interaction testing quickly and effectively! 


GET CMOCK

DOWNLOAD ZIP

This ZIP will give you the latest snapshot off github: Source. Docs. Examples. Scripts. Everything you need to get mocking!

GIT IT

git clone https://github.com/ThrowTheSwitch/CMock.git git pull

(or go see cmock on github)