CPP FakeIt library multiple inheritence
Asked Answered
I

2

6

I'm comparing GoogleMock vs FakeIt for writing unit tests. I like FakeIt over GoogleMock because I'm from Java background and FakeIt sticks close to Mockito/JMock syntax which make using the library much easier to write & maintain.

But FakeIt GIT home (https://github.com/eranpeer/FakeIt) says it doesn't support MultipleInheritance and the application im testing has code with multiple inheritance. I dont have to support diamond inheritance, so I would like to know if its just that aspect of multiple inheritance thats not supported or are there other aspects thats not supported as well?

Inositol answered 10/11, 2015 at 21:3 Comment(0)
U
3

Unfortunately it seems that any type of multiple inheritance is not supported, even if it's just an "interface" that unifies several other "interfaces", e.g.:

struct IA { virtual void a() = 0; };
struct IB { virtual void b() = 0; };
struct IC : public IA, public IB {};
fakeit::Mock<IC> mock; // error :(

(The check is done using std::is_simple_inheritance_layout<T>)

I did, however, find a little workaround for this problem, at least for simple scenarios:

class MockC : public IC {
public:
    MockC(IA& a, IB& b) : m_a(a), m_b(b) {}
    void a() override { return m_a.a(); };
    void b() override { return m_b.b(); };
private:
    IA& m_a;
    IB& m_b;
};

fakeit::Mock<IA> mockA;
fakeit::Mock<IB> mockB;
MockC mockC(mockA.get(), mockB.get());
// Use mockA and mockB to set up the mock behavior the way you want it.
// Just make sure not to use mockC after they go out of scope!
Unrefined answered 8/2, 2017 at 16:6 Comment(0)
M
2

Here's another workaround that doesn't require you to make a special mock class. All you need to do is to mock each of the base classes, and apply it to an instance of the deriving class by casting the deriving class to a reference of each interface. You do need to apply the mock to an instance of the class. Here is an example:

class I1
{
public:
    virtual int one() = 0;
};

class I2
{
public:
    virtual int two() = 0;
};

class Both : public I1, public I2
{
public:
    virtual int one()
    {
        return 0;
    }
    virtual int two()
    {
        return 0;
    }
    virtual int three()
    {
        return one() + two();
    }
};

We have pure interfaces I1 and I2 with pure virtual methods one() and two() respectively, all implemented by Both. As you might guess, Both is deliberately designed to produce an incorrect answer to demonstrate the mock. Here is the mock inside a Google Test test:

TEST(both_mock, three)
{
    Both both;
    Mock<I1> mock1((I1&)both);
    Mock<I2> mock2((I2&)both);

    When(Method(mock1, one)).Return(1);
    When(Method(mock2, two)).Return(2);

    ASSERT_EQ(both.three(), 3);
}

And this works and passes. The advantage of this is that you don't need to create a special mock class, and you can use the actual class that inherits multiple classes. The disadvantages are...

  • The deriving class (both in this case) must be instantiable (e.g., you can't do this with an abstract class or interface that inherits from other abstract classes or interfaces).
  • If you further subclass the subclass of both interfaces (e.g., class More : public Both), you still need one mock for each interface/base class, and you cannot mock any member declared by Both, More, or any further deriving class.
Maulstick answered 11/10, 2018 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.