2

I am new to google test and google mock so I am still a little bit confused. I just tried to implement a simple calculator with integer addition, multiplication and division and create a mock for it which follows real behaviours. How can I fix it or where I did wrong?

Also can you explain to me how can I be sure that it is mocking the original class instead of directly calling the original class? Thank you ahead.

Here is CBasicMath.hpp:

#ifndef BASIC_MATH_HPP__
#define BASIC_MATH_HPP__

class CBasicMath
{
public:
    CBasicMath(){}
    virtual ~CBasicMath() {}
    virtual int Addition(int x, int y);
    virtual int Multiply(int x, int y);
    virtual int Divide(int x, int y);
};

#endif //BASIC_MATH_HPP__

Here is CBasicMath.cpp:

#include "CBasicMath.hpp"

int CBasicMath::Addition(int x, int y)
{
   return (x + y);
}

int CBasicMath::Multiply(int x, int y)
{
   return (x * y);
}

int CBasicMath::Divide(int x, int y)
{
   return (x / y);
}

Here is mock_basic_test.cpp:

#include "gmock/gmock.h"
#include "CBasicMath.cpp"

using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;

class MockBasicTest : public CBasicMath {
public:
    MockBasicTest() {
    // By default, all calls are delegated to the real object.
    ON_CALL(*this, Addition(_))
        .WillByDefault(Invoke(&real_, &CBasicMath::Addition));
    ON_CALL(*this, Multiply(_))
        .WillByDefault(Invoke(&real_, &CBasicMath::Multiply));
    ON_CALL(*this, Divide(_))
        .WillByDefault(Invoke(&real_, &CBasicMath::Divide));
  }
    MOCK_METHOD2(Addition, int(int x, int y));
    MOCK_METHOD2(Multiply, int(int x, int y));
    MOCK_METHOD2(Divide, int(int x, int y));
private:
    CBasicMath real_;
};

Here is TestBasicMath:

#include "mock_basic_test.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"

class BasicMathTest : public ::testing::Test {
protected:
    BasicMathTest() {}

    virtual ~BasicMathTest() {}

    virtual void SetUp() {
        mTestObj = new CBasicMath();
    }

    virtual void TearDown() {
        delete mTestObj;
    }
    CBasicMath *mTestObj;
};

TEST_F(BasicMathTest, testAddition) {
    MockBasicTest basictest;
    EXPECT_CALL(basictest, Addition(2,3))
        .Times(1);
    EXPECT_EQ(5,basictest.Addition(2,3));
}

TEST_F(BasicMathTest, testMultiply) {
    EXPECT_EQ(6,mTestObj->Multiply(2,3));
}

TEST_F(BasicMathTest, testDivide) {
    EXPECT_EQ(6,mTestObj->Divide(6,1));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

It gives me errors like the following for all three functions:

In file included from /home/gmock-1.7.0/include/gmock/gmock-generated-function-mockers.h:43:0,
                 from /home/gmock-1.7.0/include/gmock/gmock.h:61,
                 from mock_basic_test.h:1,
                 from TestBasicMath_GoogleTest.cpp:1:
mock_basic_test.h: In constructor ‘MockBasicTest::MockBasicTest()’:
mock_basic_test.h:12:30: error: no matching function for call to ‘MockBasicTest::gmock_Addition(const testing::internal::AnythingMatcher&)’
     ON_CALL(*this, Addition(_))
                             ^
mock_basic_test.h:12:30: note: candidate is:
In file included from /home/gmock-1.7.0/include/gmock/gmock.h:61:0,
                 from mock_basic_test.h:1,
                 from TestBasicMath_GoogleTest.cpp:1:
mock_basic_test.h:19:2: note: testing::internal::MockSpec<int(int, int)>&MockBasicTest::gmock_Addition(const testing::Matcher<int>&, const testing::Matcher<int>&)
  MOCK_METHOD2(Addition, int(int x, int y));
  ^
mock_basic_test.h:19:2: note:   candidate expects 2 arguments, 1 provided

Thank you again for any help.

caiy
  • 331
  • 1
  • 3
  • 9
  • Your include-guard is illegal, see [here](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797) for details. – Baum mit Augen Oct 21 '14 at 16:15
  • @BaummitAugen people who mimic system header files are doomed to UB. – Yakk - Adam Nevraumont Oct 21 '14 at 16:32
  • @BaummitAugen Thanks. I changed to BASIC_MATH_HPP_ but it still doesn't work. – caiy Oct 21 '14 at 17:41
  • @caiy _"Thanks. I changed to BASIC_MATH_HPP_ but it still doesn't work."_ That's a valid, but minor point regarding the original question, and shouldn't be taken as answer to solve your problem. – πάντα ῥεῖ Oct 21 '14 at 20:12

2 Answers2

3

In your mocking class constructor code

ON_CALL(*this, Addition(_))
    .WillByDefault(Invoke(&real_, &CBasicMath::Addition));

the number of matchers (_) need to be the same as the number of parameters defined for the function signature:

ON_CALL(*this, Addition(_,_))
                    //   ^^  Add an additional matcher
    .WillByDefault(Invoke(&real_, &CBasicMath::Addition));

// ...

MOCK_METHOD2(Addition, int(int x, int y));
                        // ^^^^^  ^^^^^ here you have 2 parameters need matching
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Thank you so much for your help. Do you know if there is an easier way to mock real behaviour since I have a really big project that requires testing. Thank you again. – caiy Oct 21 '14 at 18:12
  • @caiy Also note: Your way to put your current class under test as being a mock delegate **looks a bit weird for me**. You simply should have an instance of your testling per test case usually, and provide mocks, that are expected to be called from these ones from a particular member function call. – πάντα ῥεῖ Oct 21 '14 at 21:12
  • I am not sure what you meant. Can you give me an example or restructure my class to show me? Thank you. – caiy Oct 22 '14 at 13:36
  • @caiy Well as your sample test looks now, you wouldn't need a mock object. Why aren't you simply testing an instance of the real class `CBasicMath`? E.g. `CBasicMath cbm; EXPECT_EQ(5,cbm.Addition(2,3));`. – πάντα ῥεῖ Oct 22 '14 at 13:40
  • I have more complex classes to test as a whole project. They have a lot of dependencies on them. So I am just testing out the functionalities of gtest and gmock by this simple class. – caiy Oct 22 '14 at 13:43
  • @caiy Then it's OK IMHO. I guessed it's just a simple example, to play with the feature. – πάντα ῥεῖ Oct 22 '14 at 13:45
0

This only works when "T real_" can be default constructed. In addition you get another copy of T within your mock, which is not needed.

Imho you can do like this, since you are accessing the base class either way:

ON_CALL(*this, Addition(_))
    .WillByDefault(Invoke(*this, &CBasicMath::Addition));

This way the call is just delgated to the base class.