Package: deride
DerideDeride (pronounced /de'ride/) is a tool which produces a mock for a C/C++ file:
it analyses the input.hheader file usingclangand
generates a new.cppfile containing the implementation of the mock object
and a.hheader file which can be used to interface with the mock object.For each method in the input class Deride generates a method in the mock
controller which can be used to install a callback to be invoked whenever the
original method is invoked.NOTE: Deride is still a work-in-progress, has not been tested but on a
handful of files, and is likely to crash on non-trivial input (in any case,
should encounter such issues, pleasefile a
bug). It may be that the generated
files are not usable as-is, but need manual editing.Example usagederide--patternMyClassmy_class.hThis will generate two files,mock_my_class.handmock_my_class.cpp, which
you should link to your unit tests instead of the real MyClass implementation:
these files will provide a mock implementation of MyClass which you can control
and inspect in your tests.For example, ifhorse.hcontains this class:classHorsePrivate;classHorse{public:Horse(conststd::string&name);Horse(Horse&&other);virtual~Horse();std::stringname()const;voidjump();floatjumpHeight()const;voidsetColor(conststd::string&colorName);std::stringcolor()const;private:HorsePrivate*d_ptr;};once Deride has run it will have createdmock_horse.hcontaining aMockHorseobject having these methods:classMockHorse{// ...staticvoidonConstructorCalled(std::function<void(conststd::string&)>callback);staticvoidonConstructorCalled(std::function<void(Animals::Horse&&)>callback);voidsetNameResult(std::stringresult):voidsetJumpHeightResult(floatresult);voidsetColorResult(std::stringresult);voidonNameCalled(std::function<std::string()>callback);voidonJumpCalled(std::function<void()>callback);voidonJumpHeightCalled(std::function<float()>callback);voidonSetColorCalled(std::function<void(conststd::string&)>callback);voidonColorCalled(std::function<std::string()>callback);// ...};That is, for each method returning a value Deride generates a method calledset<method>Result()which allows you to inject the desired result. In
addition to that, you can register a callback to be invoked every time that a
method is called. This allows you both to monitor how many times a method is
called (and with what params) and to provide its implementation; please note
that if you use the callback mechanism than the return value from the callback
will be used as the function's return value, instead of the one set viaset<method>Result()).Creating a mock objectSo, how do you get a mock object? There are a couple of ways, and which one you
use depends on the way that the target objects are instantiated:If you expect only an instance of the object to get instantiated, then you
can safely create the mock object on the stack as soon as your test starts:MockHorsemock;mock.onConstructorCalled([](conststd::string&name){// This code is executed when the tested code creates a Horsestd::cout<<"A horse has been created: "<<name;});mock.onNameCalled([](){...});If the test code creates several instances of the Horse class (well, you can
do it even for a single one, but this method is especially useful when there
are many of them), you can create a mock object for a given Horse instance
by calling themockFor()method:run_my_test_code();// somehow, you get a handle to a `Horse*` in the variable `horse`. Then you// can do:MockHorse*mock=MockHorse::mockFor(horse);mock->onNameCalled([](){...});And if you don't even have a way to retrieve a handle for theHorseobjects, you can call thelatestInstance()method:run_my_test_code();// Get a mock for the latest (newest) instance of the Horse class createdMockHorse*mock=MockHorse::latestInstance();mock->onNameCalled([](){...});Using a combination of the first solution and the previous one, it's
possible to handle more complex cases (seeexamples/many-mocks/test_program.cppfor a full example):Mock*mockTom;Mock*mockDick;Mock*mockHarry;Animals::MockHorse::onConstructorCalled([&](conststd::string&name){std::cout<<"Horse instantiated: "<<name<<std::endl;if(name=="Tom"){mockTom=Mock::latestInstance();}elseif(name=="Dick"){mockDick=Mock::latestInstance();}elseif(name=="Harry"){mockHarry=Mock::latestInstance();}});Mocking C librariesDeride can also mock plain C libraries, but for convenience the generated mock
will still be a C++ object, so that one can use lambda functions to register
the monitoring callbacks.A singleMockfile will be generated, containing theon<method>Called()registration functions and (for functions returning a value) theset<method>Return()setters.The small project underexamples/lmdb/shows how to generate and use a mock
object for the Clmdblibrary.