Mocking support in CppUTest

I've added mocking support to the CppUTest C/C++ unit testing framework. Id like to clarify why I've added it, why I've added it the way it is and how you can use it.

Why mocking?

I won't cover why mocking and state-based TDD vs interaction-based TDD. There are other wonderful descriptions of this. For example:

When working in C++, I mainly used state-based TDD with sometimes handcrafted mocks. I've stayed away from most mocking frameworks as I didn't like them much (though google mock is quite nice). Neither do I prefer interaction based over state based or the other way around, both are tools and are useful in different situations.

Why CppUTest mocking?

I always want to keep CppuTest small and clean. We (mainly me and James Grenning) have quite strict design guidelines for CppUTest. No major C++ features ought to be used, such as rtti, expection handling, templates, and STL. The main reason is that we work a lot for embedded software and embedded C++ compilers aren't that good. A smaller C++ set leads to greater and easier portability. To keep it simple, I've never really wanted to add mock support. But recently I've changed my mind and added it to the CppuTestExt (extensions) library.

Why did I changed my mind? Well... when working on a piece of code... I figured that an interaction-based approach would be best to test-drive it (lots of interaction, few state). I started to build manual mocks, as I always do in that situation, and was getting annoyed. Why was I getting annoyed? Exactly because I always do.... the same thing... and was getting bored by that. Therefore I decided to extract the things I do manually into mocking support.

But why not use one of the existing mocking frameworks like googlemock, mockpp, MockItNow, CMock? Important, because we don't want to re-invent the wheel again. My reasons for not using any of these:

  • Need to use the same limited set of C++ as CppUTest
  • No code generation
  • No or very few macros
  • Wanted to use it in CppUTest but don't want a dependency to other frameworks

All existing frameworks failed to meet the criteria (yeah, I know, the last criteria is unfair and per definition all frameworks will not meet that).

What were my major design criteria? Simplicity. Also instead of mocking automatically, I wanted to make manual mocking easier. Manual mocking won't go away in C++ and being able to do that with nearly the same ease as automatic mock generation would be a Good Thing. Also, the syntax needs to be easy and it ought to be possible to use the same mocking in C and C++.

In other words, the mocking support needs to be non-controlling and non-invasive.

There we have it. That's why I've build it... but how does it work?

How does it work?

The only class you really need to use it is MockSupport (in CppUTestExt/MockSupport.h). There are a lot more classes under the hood, but usually you don't need to use these (except for the MockFunctionCall interface).

Usually I just create one of the MockSupport and dump it in global static namespace in my test, something like:

MockSupport mock;

(this is safe as the constructor/destructor don't do a thing)

In a test, if you except a call to a certain function, you do:

mock.expectOneCall("functionName");

Then at the end of your test, you need to check that this happened with:

mock.checkExpectations();

Thats basically all you need :) Oh, of course, you still need to make the actual call :P You can do this by putting a call to mock.actualCall inside the manual mock, like:

mock.actualCall("functionName");

(yes, you still have to create a manual mock! That's the whole point :) Yes, you can let the manual mock do whatever you want it to do still too.

What about parameters?

How do we deal with parameters? Simple. In our expect call you write:

mock.expectOneCall("functionName").withParameter("parameterName", 10);

Now the mocking support expects one parameter of value 10. In the actual call you put:

mock.actualCall("functionName").withParameter("parameterName", parameter);

You can pass however many parameters, for example:

mock.expectOneCall("functionName").withParameter("p1", 1).withParameter("p2", 2);

etc etc.

What about different types?

Also, same and easy. You add to the test:

mock.expectOneCall("functionName").withParameterOfType("typeName", "parameterName", objectPtr);

And, you probably already guess the actual call:

mock.actualCall("functionName").withParameterOfType("typeName", "parameterName", paraPtr);

The only problem is how to compare these types. For that, you'll need to create and install a Comparator. How? For example:

class MyTypeComparator : public MockParameterComparator
{
public:
  virtual bool isEqual(void* object1, void* object2)
  {
     return ((MyType*)object1)->field == ((MyType*)object2)->field;
  }
  virtual SimpleString valueToString(void* object)
   {
     return StringFrom(((MyType*)object)->field);
  }
};

Then you create one and install it like:

mock.installComparator("TypeName", myTypeComaprator);

That's it for now. This covers for most of my own mocking needs, so I stopped. We want to keep things simple and clear, and this is simple and clean.

You want to have more examples? I added an example to the CppUTest/Examples. You can find it here

How to use it?

Right now, its on the trunk. So you need to grab the trunk. Its not in the zipped releases yet.

Also its part of CppUTest extensions. You can make them with:

make extensions

It will produce a library at:

lib/libCppUTestExt.a

What next?

The main functionality I wanted is there. I don't want to make it too complex, but gradually add some more. My current wishlist for the next weeks is:

  • Support for return values
  • Support for checking the right object is called
  • A C interface
  • Support for comparators that aren't just for types (like Matchers)

With those, I think the main mocking functionality I use is implemented.

I'd love feedback and bug reports (of course, there aren't any bugs :P)

Read more

จักระกับระบบประสาท

จักระกับระบบประสาท

ครูณาส่งหนังสือที่ครูแปล ชื่อ Becoming super natural มาให้ ผมได้ข้อมูลที่ตื่นตาตื่นใจหลายอย่าง หลายอย่างผมก็ยังต้องใช้เวลาค่อย ๆ ทำความเข้าใจไป แต่วันนี้อยากเอาเรื่อง จักระ ทั้ง 8 จุดมาแบ่งปัน จากในหนังสือ ผมได้ลองนั

By Chokchai
Scrum master focus

Scrum master focus

ครั้งแรกที่ผมได้เรียนว่า สกรัมมาสเตอร์ควรแบ่งโฟกัสการโค้ชของตัวเองเป็น 4 เรื่องคือ 1. องค์กร 2. engineering practice 3. product owner 4. ทีม ผมอดคิดไม่ได้ว่าคนบ้าอะไรจะไปเก่งทั้ง 4 อย่างซึ่งมันใช้ความรู้และทักษะที่แตกต่างกันเหลือเกิ

By Chokchai
Community of Practice (CoP) คืออะไร?

Community of Practice (CoP) คืออะไร?

กาลครั้งหนึ่ง… ชมรม Community of Practice (CoP) เป็นคอนเซปต์ที่ถูกกล่าวถึงใน Large Scale Scrum เทียบง่าย ๆ ก็เหมือนชมรมตอนเราเรียน ม. ปลาย นั่นแหละ ใครสนใจเรื่องอะไร ก็ไปเข้าชมรมนั้น แล้วก็ไปทำกิจกรรมร่วมกันในเรื่องที่เราสนใจ เพื่อฝึกฝนและแลกเปลี่ยนความรู้ บางทีอาจจะมี

By Chokchai