Search code examples
c++unit-testinggoogletestgooglemock

How to get around not passing a copyable object to the MATCHER within MOCK_METHOD?


I am attempting at having a MOCK_METHOD BarClass::Bar throw an exception however I seem to be running into a following error

error: call to implicitly-deleted copy constructor of 'FooMock'

And it's probably happening at the == inside MATCHER_P.

It seems as though MOCK_METHOD creates a data member that's not copyable however that leaves me with an option to use a pointer, which I can't really use since BarClass::Bar takes fooMock as a reference.

Is there a way to pass a dereferenced object to Matcher?

class FooClass
{
    public:
    virtual void Foo() const{}
};

class FooMock : public FooClass
{
    public:
    MOCK_METHOD(void, Foo, (), (const override));
};

struct BarClass
{
    void Bar(const FooMock& fooMock) {}
};

class BarMock : public BarClass
{
    public:
    MOCK_METHOD(void, Bar, (FooMock& fooMock), (const override));
};

MATCHER_P(Matcher, fooMock, "")
{
    return arg == fooMock;
}

ACTION(MyThrowException)    
{
  throw std::invalid_argument("Some exception thrown!");
}

TEST(UtClass, Test)
{
    auto fooMock = std::make_shared<FooMock>();
    BarMock barMock;
    
    EXPECT_CALL(barMock, Bar (Matcher(*fooMock))) // <-- problem here
            .Times(1)
            .WillRepeatedly(MyThrowException());

    barMock.Bar(*fooMock);       // should throw
}

https://godbolt.org/z/rEGzxjoaY


Solution

  • Arguments to matchers are passed by copy per default. This is somewhat documented here. You can fix this by wrapping your argument in std::ref() or better std::cref() so you can't accidentally modify it:

        EXPECT_CALL(barMock, Bar (Matcher(std::cref(*fooMock))))
                .Times(1)
                .WillRepeatedly(MyThrowException());
    

    https://godbolt.org/z/1r695brK4