Domanda

I have a class which carries a couple of dependencies which I'd like to mock using Google Mocks, in order to test the class with Google Test.

Simplified, I have the following1:

template<typename TDep>
class SUT {
private:
    TDep dependency;

public:
    explicit SUT(const TDep& dep) : dependency(dep) { }
    SUT(const SUT& other) : dependency(dep.other) { }

    // some methods that use the dependency
}

I also have an interface for the dependency,

class IDependency {
public:
    virtual double calculateCoolStuff(double) const = 0;
    virtual ~IDependency() { };
}

and a mock object

class MockDependency {
public:
    MOCK_CONST_METHOD1(calculateCoolStuff, double(double));
};

However, when I try to compile something like

MockDependency mock;
SUT sut(mock);

I get errors stating error: use of deleted function MockDependency(const MockDependency&), i.e. there is no copy-constructor of the mocked object. I found this discussion on Google Groups which basically ends in making mock objects non-copyable, but allowing the user to add a copy constructor and define copy behavior manually. Very well:

class MockDependency {
public:
    MockDependency(const MockDependency& other) { }
    MOCK_CONST_METHOD1(calculateCoolStuff, double(double));
};

Now my code compiles, but if I run something like

MockDependency mock;
SUT sut(mock);

EXPECT_CALL(mock, calculateCoolStuff(2.0)).WillRepeatedly(Return(3.0));

sut.doStuff(); // Calls calculateCoolStuff

in a test, I get an error stating that the call was never set up. In other words, the instance mock which I can use to setup expectations, is no longer the same as the instance on SUT used for calculations. This makes testing with GMock and DI difficult, to say the least...

What is the best solution to this?


1) Yes, I'm using poor man's DI. Not the topic of this conversation...

È stato utile?

Soluzione

You can use dependency injection with references by ensuring that your class member is a reference:

template<typename TDep>
class SUT {
private:
    TDep& dependency;  // Reference

    // etc.
}

Note that you no longer need a copy constructor on MockDependency. As a rule, you need access to all instances of mock objects being used by your SUT to set up expectations on them.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top