4

I have a function1 inside which function 2 is called. I have to mock only function2, whwenever i call function1 it should call real implementation of function1 and mock implementation of function2. Kindly help me on this

Display.cpp

    #include "Display.h"
int DisIp::getip()
{

return 5;

}
int  DisIp::display()
{
        Addition obj;
        int ip=obj.getip();
    return ip;
}

Display.h

class DisIP
{
public:
    int display();
        int getip();
};

GMOCK file

#include <limits.h>
#include "gmock.h"
#include "gtest.h"
#include "Display.h"
#include <string>
using namespace std;
using ::testing::AtLeast;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Gt;
using ::testing::Return;
using testing::ReturnPointee;
using ::testing::Invoke;
class MyInterface{
public:

    virtual int display() = 0;
    virtual int getip()=0;
};

class MockInter : public MyInterface
{
public:
MockInter()
{
        ON_CALL(*this, getip()).WillByDefault(Invoke(&this, &MockInter::getip));
        ON_CALL(*this, display()).WillByDefault(Invoke(&real, &Addition::display));
}
MOCK_METHOD0(display,int());
MOCK_METHOD0(getip,int());
DisIp real;
};


class DisplayTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
  }

  virtual void TearDown() {
    // Code here will be called immediately after each test
    // (right before the destructor).
  }
};

TEST_F(DisplayTest,ip){
        MockInter mock;
//EXPECT_EQ(1,mock.display());
EXPECT_EQ(1,mock.getip());
}
273K
  • 29,503
  • 10
  • 41
  • 64
  • I am afraid this ` ON_CALL(*this, getip()).WillByDefault(Invoke(&this, &MockInter::getip));` is infinite recursion... – PiotrNycz Mar 06 '17 at 07:58

2 Answers2

1

Your design suffers from breaking Single Responsibility Principle.

Displaying and getting IP are two different responsibilities. It is even shown in your implementation of DisIp::display() - you get IP from so-called Addition obj. When you fix this design error - your unit tests becomes much easier and straightforward. But it is important to say that UT are only the symptom here, the bad design is a disease.

So how it could look like:

class IIpProvider
{
public:
  virtual ~IIpProvider() = default;
  virtual int getIp() = 0;
};

class DispIp
{
public:
    DispIp(IIpProvider& ipProvider) : ipProvider(ipProvider) {}
    int display()
    {
       int ip=ipProvider.getIp();
       //...
       return ip;
    }
private:
   IIpProvider& ipProvider;
};

then your Mock:

class IpProviderMock : public IIpProvider
{
public:
  MOCK_METHOD0(getIp, int());
};

And your tests:

class DispIpTest : public ::testing::Test
{
protected:
   IpProviderMock ipProviderMock;
   DispIp objectUnderTest{ipProviderMock}; // object-under-test must be connected to object doubles (like mocks)
};
TEST_F(DispIpTest, shallUseProvidedIpToDisplay)
{
    using namespace testing;
    auto SOME_IP = 7;
    EXPECT_CALL(ipProviderMock, getIp()).WillRepeatedly(Return(SOME_IP));
    //...
    ASSERT_EQ(SOME_IP, objectUnderTest.display());
}

In your original tests - main problem was also that your mock object was not connected in any way to your object under test.


If you do not like (cannot) to change your design (what I really advice) you have to use technique called partial mocking

In your case - it would something like this:

class DisIP
{
public:
    int display();
    virtual int getip(); // function for partial mocking must be virtual
};
class DisIPGetIpMock : public DisIP
{
public:
      MOCK_METHOD0(getIp, int());
};
class DispIpTest : public ::testing::Test
{
protected:
   DisIPGetIpMock objectUnderTest; 
};

TEST_F(DispIpTest, shallUseProvidedIpToDisplay)
{
    EXPECT_CALL(objectUnderTest, getIp()).WillRepeatedly(Return(SOME_IP));
    ...
    ASSERT_EQ(SOME_IP, objectUnderTest.display());
}
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • First snippet (not the partial mocking one) is not compiling. I am getting error:gtest5.cpp: In constructor ‘DisIP::DisIP(IIpProvider&)’: gtest5.cpp:26:63: error: invalid initialization of reference of type ‘IpProviderMock&’ from expression of type ‘IIpProvider’ gtest5.cpp: At global scope: gtest5.cpp:40:31: error: ‘ipProviderMock’ is not a type gtest5.cpp: In member function ‘virtual void DispIpTest_shallUseProvidedIpToDisplay_Test::TestBody()’: gtest5.cpp:46:5: error: ‘((DispIpTest_shallUseProvidedIpToDisplay_Test*)this)->DispIpTest::objectUnderTest’ does not have class type – Dipankar Saha Jun 05 '17 at 06:52
  • @DipankarSaha Not sure if that was the problem - but the destructor name of `IIpProvider` was wrong. Now it is corrected. – PiotrNycz Jun 05 '17 at 07:57
  • That I had corrected that in my test code so this one is not the problem. Not sure why following line is giving problem. "DispIp objectUnderTest{ipProviderMock};" Though I guess instead of "{}" it would be "()" -> gtest5.cpp:40:31: error: ‘ipProviderMock’ is not a type – Dipankar Saha Jun 05 '17 at 11:02
  • @DipankarSaha corrected - now it compiles. It was just typos - like `DisIP` -> `DispIp`... – PiotrNycz Jun 05 '17 at 20:29
  • As in one comment is not able to accommodate the error I am getting from compiler so writing in separate comment. $ g++ -isystem /home/dipankar/Downloads/googletest-master/googletest/include/ -isystem /home/dipankar/Downloads/googletest-master/googlemock/include/ -pthread gtest9.cpp /home/dipankar/Downloads/googletest-master/googlemock/make/libgmock.a gtest9.cpp:14:28: warning: defaulted and deleted functions only available with -std=c++0x or -std=gnu++0x [enabled by default] gtest9.cpp:14:28: error: ‘virtual IIpProvider::~IIpProvider()’ declared virtual cannot be defaulted in the class body – Dipankar Saha Jun 06 '17 at 09:44
  • gtest9.cpp:32:7: error: looser throw specifier for ‘virtual IpProviderMock::~IpProviderMock()’ gtest9.cpp:14:11: error: overriding ‘virtual IIpProvider::~IIpProvider() throw ()’ gtest9.cpp:42:11: error: function definition does not declare parameters gtest9.cpp: In member function ‘virtual void DispIpTest_shallUseProvidedIpToDisplay_Test::TestBody()’: gtest9.cpp:47:10: error: ‘SOME_IP’ does not name a type gtest9.cpp:48:64: error: ‘SOME_IP’ was not declared in this scope gtest9.cpp:50:5: error: template argument 1 is invalid – Dipankar Saha Jun 06 '17 at 09:45
  • gtest9.cpp:50:5: error: ‘objectUnderTest’ was not declared in this scope – Dipankar Saha Jun 06 '17 at 09:45
  • Can you show me how your are compiling. The way I am compiling is given above (along with the error log). – Dipankar Saha Jun 06 '17 at 09:47
  • @DipankarSaha I am compiling with -std=c++14 (gcc5,3). I see that your compiler is quite old. If you have errors like " ‘virtual IIpProvider::~IIpProvider()’ declared virtual cannot be defaulted in the class body" then replace its implementation with pre-C++11 style, like `virtual ~IIpProvider() {}` – PiotrNycz Jun 06 '17 at 10:39
  • Ok. Now I am getting: `gtest9.cpp:42:11: error: function definition does not declare parameters gtest9.cpp: In member function ‘virtual void DispIpTest_shallUseProvidedIpToDisplay_Test::TestBody()’: gtest9.cpp:49:5: error: ‘objectUnderTest’ was not declared in this scope`. So basically I getting error in this line `DispIp objectUnderTest{ipProviderMock};` – Dipankar Saha Jun 06 '17 at 11:00
  • Also to mention it if I make `DispIp objectUnderTest(ipProviderMock);`. Then getting the below error: `gtest9.cpp:42:27: error: ‘ipProviderMock’ is not a type gtest9.cpp: In member function ‘virtual void DispIpTest_shallUseProvidedIpToDisplay_Test::TestBody()’: gtest9.cpp:48:5: error: ‘((DispIpTest_shallUseProvidedIpToDisplay_Test*)this)->DispIpTest::objectUnderTest’ does not have class type` – Dipankar Saha Jun 06 '17 at 11:03
  • 1
    @DipankarSaha Because you do not have in-class initialization in your compiler -- see https://stackoverflow.com/questions/13662441/c11-allows-in-class-initialization-of-non-static-and-non-const-members-what-c You cannot expect that people will use "ancient" C++ to make your old compiler happy. You should google or ask to SO about your compiler warnings - or just use `-std=c++11` at least in your commandline. I mean - in the current mode, when I am looking at your problems once a day - it will take weeks until you make it compiled... – PiotrNycz Jun 06 '17 at 13:32
  • Hi PiotrNycz, Thank you very much. Indeed due to my older compiler it was not getting compiled. Thanks :) – Dipankar Saha Jun 07 '17 at 05:42
0

You can use the Cutie library to mock C function GoogleMock style, if that will assist you.
There's a full sample in the repo, but just a taste:

INSTALL_MOCK(fclose);
CUTIE_EXPECT_CALL(fclose, _).WillOnce(Return(i));
MrDor
  • 98
  • 5