1

It looks like I can not use virtual inheritance when trying to mock interfaces. I need to use virtual inheritance because my code depends on a third-party library. The 3rd-party library uses virtual inheritance to cast from one child to another, through the parent. We need to be able to mock according to the expectations of the 3rd-party library, but this is not the case.

Note: IA, IB, IC, and ID are a 3rd party library

class IA
{
};

class IB :virtual public IA
{
};

class IC :virtual public IB
{
public:
    int getValue(){}
};

class ID : virtual public IA
{ 
public:
    void type(){};
};

class MockD :
              public ID 
    //virtual public ID; fails all of my tests that depends on ID
{
public:
    MOCK_METHOD0(type, void())
}; 

class MockC :
    //virtual public IC, virtual public MockD{}; //throws an exception for accessing pD->type()
    //        public IC, virtual public MockD{}; //throws an exception for accessing pD->type()
    //virtual public IC,         public MockD{}; //throws an exception for accessing pC->getValue()
    //        public IC,         public MockD{}; //throws an exception for accessing pD->type() 
{
    MOCK_METHOD0(getValue, void());

};
//throws an exception for accessing pD->type()


           IA
        _______
    (v)/       \(v)
      IB        ID
   (v)|         |
     IC       MockD
      |         |
    (v)\        /(v)   
         MockC


           IA
        _______
    (v)/       \(v)
      IB        ID
   (v)|         |
     IC       MockD
      |         |
      \        /(v)   
         MockC           


           IA
        _______
    (v)/       \(v)
      IB        ID
   (v)|         |
     IC       MockD
      |         |
      \        /   
         MockC           

//throws an exception for accessing pC->getValue()

           IA
        _______
    (v)/       \(v)
      IB        ID
   (v)|         |
     IC       MockD
      |         |
   (v)\        /   
         MockC           
           IA

Code to be tested

ID* pD = dynamic_cast<ID*>(pC);
pD->type();
pC->getValue();

// in the test

MockC* mockC = new MockC();
EXPECT_CALL(mockC, type());
EXPECT_CALL(mockC, getValue());
273K
  • 29,503
  • 10
  • 41
  • 64
hamaney
  • 454
  • 7
  • 16

1 Answers1

0

You just want Mock object that derives from ID and mock all its functions. Then forget about MockC and just define MockD in a way you need:

class MockD : public ID 
{
public:
    MOCK_METHOD0(type, void());
    MOCK_METHOD0(getValue, int());
}; 

And setup your test expectation in this way:

MockD mockD;
EXPECT_CALL(mockD, type());
EXPECT_CALL(mockD, getValue()).WillOnce(Return(0)); //not sure you want zero - use return value that you needs

Then - assuming this is void codeUnderTest(IC& c) - the code you want to test - just pass mockD to this code:

codeUnderTest(mockD);

In case you need both MockD and MockC for some other reasons - then use template definitions to achieve this goal:

template <typename Interface>
class MockCT : public Interface
{
public:
    MOCK_METHOD0(getValue, int());
};
using MockC = MockCT<IC>;

template <typename Interface>
class MockDT : public MockCT<Interface>
{
public:
    MOCK_METHOD0(type, void());
};
using MockD = MockDT<ID>;
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112