Introducing PowerFake for C++


PowerFake is a new mini-framework/tool to make it possible to fake/mock  free functions and static & non-virtual member functions in C++. It requires no change to the code under test, but it might need some structural changes, like moving some parts of the code to a different .cpp file; or making inline functions non-inline when built for testing.

It is useful for writing unit tests and faking/mocking functions which should not/cannot be run during a test case. Some say that such a feature is useful for existing code, but should not be needed for a code which is written testable from the beginning. But, personally I don’t agree that it is always appropriate to inject such dependencies using virtual interfaces or templates.

Currently, it is not supposed to become a mocking framework on its own. I hope that I can integrate PowerFake into at least one existing C++ mocking framework. Therefore, currently it doesn’t provide anything beyond faking existing functions.

Unlike similar solutions like CppFreeMock, Injector++(Currently Windows only), and Hippomocks(Free functions only); it doesn’t do runtime patching of functions. Probably the most similar solution is C Mock, which relies on the mocked functions to be in dynamic libraries and redefines them, but it takes a slightly different approach. Instead PowerFake relies on using GNU ld’s --wrap option to provide a replacement function for the original function while linking. Therefore, currently PowerFake is a GCC & GNU ld only solution, but it should be fairly easy to port to other linkers which provide a similar option. It also depends on the GCC implementation of type_info::name() to retrieve mangled name of a type. Therefore, porting to other compilers would need a way to extract such information too.

CppFreeMock seems to be able to satisfy my needs, but I personally doesn’t feel safe about runtime patching, specially since the code is not actively maintained and I wonder if it is guaranteed to work with any version of GCC. PowerFake solution seems safer to me, but it has its own limitations as it relies on link-time wrapping of target functions.

If the caller and called function are in the same translation unit, it won’t be intercepted by PowerFake. Also, using PowerFake needs some modifications to how test suite is built because some linker flags are generated by PowerFake, and it also needs to adjust some symbol names. It also can’t fake inline functions, and faking template functions needs some work.

Currently, support for using PowerFake in CMake projects is provided so that using it is as easy as possible. But using it with other build tools would need more work.

Example

After setting up the build system to properly integrate PowerFake, using it is fairly easy. There are 2 main steps to fake a function: 1. Marking the functions which should be faked. 2. Faking them as appropriate

For simplicity, I use a file named wrap.cpp to mark functions for faking:

#include 

#include "functions.h"
#include "SampleClass.h"

WRAP_FUNCTION(normal_func);

WRAP_FUNCTION(SampleClass::CallThis);

And now, faking the function is as simple as a MakeFake() call:

...
 normal_func(3); // Calls the real function auto normalfk = MakeFake(normal_func,
 [](int) { cout << "Fake called for normal_func(int)" << endl; }
 );
 normal_func(3); // Calls the fake function created above

 auto ccfk = MakeFake(&SampleClass::CallThis,
 []() { cout << "Fake called for SampleClass::CallThis" << endl; }
 );
 SampleClass c;
 c.CallThis();

// Fakes are in effect as while as fake objects (normalfk & 
// ccfk above) live.
...

 

Hope that somebody finds PowerFake useful too! 🙂

Advertisements

4 responses to this post.

  1. […] « Introducing PowerFake for C++ […]

    Reply

  2. […] I said in the introduction, PowerFake lacked the features of a complete mocking framework, and I was hoping to be able to […]

    Reply

  3. […] I said in the introduction, PowerFake lacked the features of a complete mocking framework, and I was hoping to be able to […]

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: