I am trying to mock a method Handler::Foo
to throw an exception that takes in two objects as parameters i.e SomeStruct
, SomeClass
. The former is created Source::Bar
on the fly whereas SomeClass
is passed from main.
I used MATCHER but it returns a single object which doesn't match with what Foo
expects (2 parameters), hence the error.
no matching function for call to 'MockHandler::gmock_Foo(MatchMatcherP2<SomeStruct, SomeClass>)'
ACTION(MyThrowException)
{
throw std::invalid_argument("Some exception thrown!");
}
TEST(UtClass, TestSourceBar)
{
auto mockHandler = std::make_shared<MockHandler>();
SomeStruct someStruct = {.a = 10};
SomeClass someClass;
EXPECT_CALL(*mockHandler, Foo(Match(someStruct, someClass)))
.Times(1)
.WillRepeatedly(MyThrowException()); // ERROR
}
Is there a way to mock Handler::Foo
such that it throws an exception?
struct SomeStruct
{
int a;
};
class SomeClass
{
public:
// some methods...
};
class Handler
{
public:
virtual void Foo(const SomeStruct&, SomeClass)
{
// stuff...
}
};
class Source
{
std::weak_ptr<Handler> _handler;
public:
Source(std::weak_ptr<Handler> handler) : _handler(handler) {}
void Bar(SomeClass someClass)
{
SomeStruct s = {.a = 10};
if (auto sp = _handler.lock())
{
sp->Foo(s, someClass); // simulate this call
}
}
};
class MockHandler : public Handler
{
public:
MOCK_METHOD(void, Foo, (const SomeStruct&, SomeClass), (override));
};
MATCHER_P2(Match, someStruct, someClass, "")
{
return arg.a == someStruct.a && arg.someClass == someClass;
}
ACTION(MyThrowException)
{
throw std::invalid_argument("Some exception thrown!");
}
TEST(UtClass, TestSourceBar)
{
auto mockHandler = std::make_shared<MockHandler>();
SomeStruct someStruct = {.a = 10};
SomeClass someClass;
EXPECT_CALL(*mockHandler, Foo(Match(someStruct, someClass)))
.Times(1)
.WillRepeatedly(MyThrowException()); // ERROR
Source source(mockHandler);
source.Bar(someClass); // should throw an exception...
}
CodePudding user response:
The matcher is meant to test some conditions for a single argument, so you would need to use a separate matcher for each one.
It's not really clear what you want to test here, but one way of doing what your example shows would be:
class SomeClass
{
public:
bool operator==(const SomeClass &) const = default;
// some methods...
};
MATCHER_P(MatchSomeStruct, someStruct, "")
{
return arg.a == someStruct.a;
}
MATCHER_P(MatchSomeClass, someClass, "")
{
return arg == someClass;
}
TEST(UtClass, TestSourceBar)
{
auto mockHandler = std::make_shared<MockHandler>();
SomeStruct someStruct = {.a = 10};
SomeClass someClass;
EXPECT_CALL(*mockHandler, Foo(MatchSomeStruct(someStruct), MatchSomeClass(someClass)))
.Times(1)
.WillRepeatedly(MyThrowException());
This will of course check the two parameters separately. If you need to check the two parameters as a whole then you could look into adding a With()
clause.