GMock std::any argument

I have an interface

class IUObject {
public:
    virtual void setProperty(const std::string& name, const std::any& value) = 0;
    virtual void setProperty(const std::string& name, std::any&& value) = 0;
};

I`ve created mock object:

class MockUObject : public IUObject {
public:
    MOCK_METHOD(void, setProperty, (const std::string& name, const std::any& value), (override));
    MOCK_METHOD(void, setProperty, (const std::string& name, std::any&& value), (override));
};

I need to test setProperty function via EXPECT_CALL. I`ve tried something like this:

MockUObject *mock = new MockUObject();
/// Some code here
EXPECT_CALL(*mock, setProperty(TypedEq<const std::string&>("position"),
                               TypedEq<std::any&&>(std::any(std::pair<double, double>(6.0, 2.0)))));

But compiler cant compare std::any:

error: no match for 'operator==' (operand types are 'const std::any' and 'const std::any')

I cant change base interface functions, so i have to work with std::any. How can i deal with this problem?

Answer

AFAIK, there is no matcher for std::any, so you need to write your own.

MATCHER_P(AnyMatcher, value, "")
{
    // assume the type of parameter is the same as type stored in std::any, 
    // will not work e.g. when any stores std::string and you pass a literal
    // you'd need to write a template matcher for that case
    return std::any_cast<decltype(value)>(arg) == value;
}

Usage:

EXPECT_CALL(*mock, setProperty(TypedEq<const std::string&>("position"),
                               AnyMatcher(std::pair<double, double>(6.0, 2.0))));

See it online (and a passing case). Note that you cannot really have overloads where one function has const lvalue reference as argument and the other rvalue reference, because that’s ambiguous (both can accept rvalue as argument).