Search code examples
c++unit-testingboostturtle-mock

Mock object with turtle mock for boost::test


I'm trying to create a unittest with mocked objects using turtle and boost. But the example doesn't work and I can't find the error. I expect no errors but the result is:

$ ./unittest 
Running 1 test case...
Start
Display: 0
End
Calculator.spec.cpp(16): error in "zero_plus_zero_is_zero": untriggered expectation: v.MockView::display
. once().with( 0 )

Calculator.h:

#ifndef CALCULATOR_H
#define CALCULATOR_H

#include "View.h"

class Calculator {
public:
    Calculator(View& v);

    void add( int a, int b ); // the result will be sent to the view 'v'
private:
    View& view;
};

#endif //CALCULATOR_H

Calculator.cpp:

#include "Calculator.h"

Calculator::Calculator(View& v)
: view(v) {}

void Calculator::add(int a, int b) {
    view.display(a + b);
}

View.h:

#ifndef VIEW_H
#define VIEW_H

class View {
public:
    View() = default;

    void display(int a);
};

#endif //VIEW_H

View.cpp:

#include "View.h"
#include <iostream>

void View::display(int a) {
    std::cout << "Display: " << a << std::endl;
}

Calculator.spec.cpp:

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE calculator
#include "Calculator.h"
#include "View.h"
#include <turtle/mock.hpp>
#include <boost/test/unit_test.hpp>

MOCK_BASE_CLASS(MockView, View) {
    MOCK_METHOD(display, 1)
};

BOOST_AUTO_TEST_CASE( zero_plus_zero_is_zero ) {
    std::cout << "Start" << std::endl;
    MockView v;
    Calculator calculator(v);
    MOCK_EXPECT(v.display).once().with(0);
    calculator.add(0, 0);
    std::cout << "End" << std::endl;
}

Makefile:

    test: Calculator.spec.cpp Calculator.cpp Calculator.h View.cpp View.h
        g++ Calculator.spec.cpp Calculator.cpp View.cpp -o unittest --std=c++11 -lboost_unit_test_framework

The unittest yields no errors when I change the test to

BOOST_AUTO_TEST_CASE( zero_plus_zero_is_zero ) {
    std::cout << "Start" << std::endl;
    MockView v;
    Calculator calculator(v);
    MOCK_EXPECT(v.display).once().with(0);
    //calculator.add(0, 0);
    v.display(0);
    std::cout << "End" << std::endl;
}

What do I miss? Where is the problem with my test?


Solution

  • Your mock object is a subclass of View and it defines display. But because display is not declared virtual in View, the base class version is being called from the unit test instead of the mock version. You can observe this because Display: 0 is present in the output of the unit test. Define View::display as virtual and it will work.