eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.23k stars 170 forks source link

Mock data member initialisation #102

Open j2bbayle opened 7 years ago

j2bbayle commented 7 years ago

Hey! Just a quick question about data member initialisation for mock object: when mocking a class with data member, which get initialisation (using a constructor or in-class initialisation), it seems that the mock object does not pick up those initialised values.

A small example:

class A {
public:
    virtual void doSomething() { }
    bool getState() const { return _state; }
protected:
    bool _state = true;
};

TEST_CASE("MyTest") {
    Mock<A> Mock;
    auto mock = Mock.get();
    REQUIRE(mock.getState());  // FAILS
}

Correct me if I'm wrong, but this is not the expected behaviour, is it?

dragospop commented 7 years ago

It is, because you mock the interface. your mock class has no functionality except the one you specify using FakeIt. What you want is spying, and this can be done like this:

A obj;
Mock<A> spy(obj);

auto mock = spy.get();
REQUIRE(mock.getState());  // should work now
j2bbayle commented 7 years ago

Oh, I see. Using inheritance though, we have to stub parent members (or use spying as you pointed out), which is less straightforward:

class A {
public:
    virtual void internalUpdate() { }
    virtual void update() {
        if (_state) { internalUpdate(); }
    }
protected:
    bool _state = true;
};

class B: public A {
public:
    void internalUpdate() override {
        // do something here
    }
};

TEST_CASE("MyTest") {
    Mock<B> mockB;
    Fake(Method(mockB, internalUpdate));
    mockB.get().update();
    Verify(Method(mockB, internalUpdate)).Once();  // FAILS
}

And in this example we cannot test the correct behaviour of B without stubbing A::update() method, or make protected data member _state public.

Using spying, I cannot even handle this simple example, but I'm certainly missing something:

TEST_CASE("MyTest") {
    B anObject;
    Mock<B> spy(anObject);
    spy.get().update();
    Verify(Method(spy, internalUpdate)).Once();  // ALSO FAILS...
}