Alice and the mock turtle
Picture courtesy Dave Kellum
Mock Objects for C++
 Around mockpp 
What is mockpp
How to use this library
Serbo-Croatian intro
The Handbook
FnAQ
A Tutorial
The API Reference
Download
Installation
Compatibility
Known problems
 
 
 Sourceforge Services 
Project summary
 Subversion
 Mailing lists
 Reporting bugs
 Forums
 
Links
AMOP: Automatic Mock Object for C++
Mock Objects for Java
jMock
EasyMock
CppUnit
developerWorks
Test Driven Development
Nautical Chart Tiles
Mock Turtle's Calculator
The Sourceforge Team
The GNU developers
Doxygen
 

 

Hot spot:

Software Patents

Patent violating contest


What is mockpp

mockpp is a platform independent generic unit testing framework for C++. It's goal is to facilitate developing unit tests in the spirit of Mock Objects for Java, EasyMock and jMock.

Mock objects allow you to set up predictible behaviour to help you test your production code by emulating some functionality your code depends on. This might for example be a huge database which is too difficult and time consuming to maintain just for testing purposes.

Originally I started with a port of Mock Objects to C++ and wanted to keep the same interfaces. But in the meanwhile I found out more about Java and it's differencens to C++ (it's funny reflection api for example ) and so I had to change a bunch of details. Additionally I included the working methods of EasyMock and jMock. From my limited understanding of Java there seems to be something similar in MockObjects but I guess EasyMock is easier to use and certainly was easier to port to C++.

How to use this library

Note: the following sections describe only the basic elements within mockpp. There are also a handbook, an api reference and a tutorial available which explain the various parts of mockpp.

Mockpp contains a number of classes, templates (and macros) which I divide into Basic Expectations and Advanced Expectations.

Basic expectations

Basic expectations cover simple actions. You create an object and tell it what is allowed. So if you want to check that a method is passed the correct parameter values you might set up a mock object with an appropriate method like this:


   ...

   void MyMockClass::initExpectation()
   {
     myIntExpectation.setExpected(123);
   }

   ....

   void MyMockClass::methodUnderTest(unsigned i)
   {
     myIntExpectation.setActual(i);
   }

  

If the passed value is 123 as expected everything is fine. Otherwise an AssertionFailedError is thrown.

There are several classes to verify simple expectations:

  • verify an exact match
  • match a range of values (mainly numerical ones)
  • set up a list to verify a series of arbitrary parameters to match one after the other
  • verify if objects occur at least once in a collection
  • verify substrings
  • verify with counter increments

Sometimes you don't want to check ingoing parameters to a method but need predictible objects coming out. In this case you set up a list with return objects:


   ...

   void MyMockClass::initReturnList()
   {
     myStringReturnList.addObjectToReturn(std::string("alice"));
     myStringReturnList.addObjectToReturn(std::string("bob"));
     myStringReturnList.addObjectToReturn(std::string("sue"));
   }

   ....

   std::string MyMockClass::methodUnderTest()
   {
     return myStringReturnList.nextReturnObject();
   }

  

One object after the other is returned in the given order. If you request one too many object an AssertionFailedError is thrown. The same applies if you don't request all objects.

For more information please refer to the basic section of the developers guide.

Advanced expectations

mockpp currently supports two different approaches to create mock objects. The first is easier to understand but rather strict. The second is more complex but offers more flexibiliy and is extensible with user defined classes. But this is also a matter of personal taste. There is a chapter which introduces into the common characteristics.

Vistable Mock Objects

The main idea is to replace your real world object with an object that simulates some limited behaviour. For that purpose you create a VisitableMockObject and the according methods. Additionally you record an execution path and feed it some parameters, some objects to return or maybe tell it to throw exceptions. All returned objects and exceptions may also be conditionally based on parameters passed to your method.

To easily feed the expected parameters into your calls you need a mock method for your mock object.


    class MyVisitableMockObject : public VisitableMockObject
    {
    public:

        MyVisitableMockObject(const String &name)
          : VisitableMockObject(name, 0)
          // constructs an internal mock method
          , visitable_mocker("visitable") this)
        {}

        // forwards the actual call to the mock method
        int visitable(unsigned u)
        {
          return visitable_mocker.forward(u);
        }

        // creates a mock method for: int visitable(unsigned);
        VisitableMockMethod<int, unsigned>  visitable_mocker;
    };

    ....

    MyVisitableMockObject mvo("mvo");

    // create a short hand reference to the mock method
    VisitableMockMethod<int, unsigned> &visitor (mvo.visit_mocker);

    // we are in record mode now:

    visitor.addReturnValue(1);                // return "1" the first time
    visitor.addReturnValue(11);               // return "11" the second time
    visitor.setDefaultReturnValue(123);       // return "123" all the other calls

    visitor.addResponseValue(0, 1);           // return "0" when passed "1"
    visitor.addResponseValue(1, 0);           // return "1" when passed "0"

    visitor.addResponseThrowable(make_throwable(int(1), 1);  // throw when passed "1"
    visitor.addResponseThrowable(make_throwable(int(0), 0);  // throw when passed "0"

    // throw std::string("string 1") when called the first time
    visitor.addThrowable(make_throwable(std::string("string 1")));

    // throw std::string("string 2") the next three times
    visitor.addThrowable(std::string("string 2"), 3);

    // throw int(123) the rest of the time
    visitor.setDefaultThrowable(make_throwable(int(123)));

    mvo.visitable(1);       // require "1" as parameter the first time
    mvo.visitable(2);       // require "2" as parameter the second time

    mvo.activate()

    // from now on all calls are verified

    mvo.visitable(1);       // verify "1" which is ok, see above
    mvo.visitable(1);       // would fail as "2" is required

    ....
  

For more information please refer to the section about vistable mock objects in the developers guide.

Chainable Mock Objects

Specifying some behaviour with the second approach called chainable mock objects is similar to describing it in words. You may say for example:

  • I expect some method invocation exactly once
  • This must happen after another invocation labeled "other-ident"
  • The method must be called with with a value which is equal to 321
  • Then the method will return 123
  • This invocation has an identifier called "ident"

In C++ code you might express the same like this:


    chainer.expects(once())
           .after("other-ident")
           .with(new IsEqual<int>(321))
           .will(new ReturnStub(123))
           .id("ident");

    

Similar to the former approach you must create a helper object to express your expectations. This is further explained in the section about chainable mock objects in the handbook.

Poor Man's Mock Objects

Most of the times you don't need a full blown mock objects library. Often some simple lines of code with a quick and dirty approach suffice. For that reason the handbook contains some simple mock object patterns that don't need further support from a library.

If you know some other patterns I would be happy if could send them to me for inclusion into the handbook.


This article is translated to Serbo-Croatian language by Jovana Milutinovich from Webhostinggeeks.com.


SourceForge Logo [Best viewed with open eyes]

Last updated on November 11. 2011
mockpp at ewald-arnold dot de