1.3.2. Visitable Mock Objects

To obtain a visitable mock object you must:

The following listing contains a short example and explains the basic features.


  class MyInterfaceClass 1
  {
    public:

     virtual int access(unsigned &index) = 0;
  }

  class MyVisitableMockObject : public VisitableMockObject,  2
                                public MyInterfaceClass
  {
    public:

      MyVisitableMockObject(const String &name)
        : VisitableMockObject(name, 0)
        , MOCKPP_CONSTRUCT_MEMBERS_FOR_VISTABLE1(access) 3
      {}

      MOCKPP_VISITABLE1(MyVisitableMockObject, int, access, unsigned); 4
  };

  MyVisitableMockObject mvo("mvo");

  MOCKPP_CONTROLLER_FOR(MyVisitableMockObject, access) access_ctr (&mvo); 5

  access_ctr.addThrowable(std::string("throw"), 2); 6
  access_ctr.addResponseValue(1, 13); 7
  access_ctr.addResponseValue(2, 37);
  access_ctr.addResponseValue(3, gt<unsigned>(50)); 8

  mvo.access(1); 9
  mvo.access(13);
  mvo.access(lt<unsigned>(123)); 10

  mvo.activate(); 11

  // use the object

  mvo.verify(); 12

1

Define your interface class.

2

Derive your mock object class from VisitableMockObject and the interface class.

3

According to the type of method and the number of parameters it takes add a macro that does the construction part for all the necessary internal helper variables for that method.

4

Similarly add another macro that implements the method with it's internal variables and helper methods.

5

Create a controller object for the method to set up it's behaviour.

6

Add some behaviour: tell the object to throw an exception when called the first and second time.

7

More specific behaviour: depending on the parameters passed it shall respond with certain return values.

8

The former controller parameters where strict and demanded exact equality. By using constraint objects it is possible to use arbitrary tolerance. In the example the parameter must be greater than 50 to return 3.

9

Describe the expected execution path and the expected parameters for the method how it shall happen in your test later. This is simply done by calling the methods.

10

Demands that the parameter value is less than 123.

11

Activate the object and use it in the tests.

12

After the tests have completed verify all conditions that are still pending, for example unused return values or exceptions.

For a deeper documentation of the methods involved with a controller see the api documentation of VisitableMockObject::Controller.

1.3.2.1. Dispatching Order

The expectations are evaluated in the following order which of course also depends on the method definition itself. Parameters to the method can only be evaluated if they exist and void methods obviously can't return any objects.

  1. verify that the expected method is called
  2. find and throw an exception based on the parameters passed
  3. if available: throw the next exception from the list created with addThrowable()
  4. throw the default exception if defined
  5. verify the values of the parameters passed
  6. find and return an object based on the parameters passed
  7. if available: return the next object from the list created with addReturnValue()
  8. return the default object

There is a subtle difference in the behaviour of versions before 1.2.x which affects topics 3. and 7. in the above list. Older versions always checked if there is an exception available and threw them in the call. Newer version on the contrary use the order from the sources.

For example take the following code fragment:


  mock.addThrowable(xx);
  mock.addReturnValue(aa);
  mock.addThrowable(yy);
  mock.addReturnValue(bb);

In this case older versions would behave as follows:

  1. throw(xx)
  2. throw(yy)
  3. return(aa)
  4. return(bb)

Newer versions on the other hand will do what is written in the code:

  1. throw(xx)
  2. return(aa)
  3. throw(yy)
  4. return(bb)

If your code relies on the old behaviour you can switch back by calling unsetThrowablesInline(). This method is available for the controller object and only influences the according method. Additionally the method is also available in the container mock object itself and affects all registered sub-objects.