I want to mock the following method Ctrl::Do(const Handler& handler)
to throw an exception.
Ctrl
stores a weak pointer to Handler
class Ctrl
{
std::weak_ptr<Handler> _handler;
// ...
};
And a reference of which gets passed to Ctrl::Do()
struct CtrlMock : public Ctrl
{
CtrlMock(std::weak_ptr<Handler> handler) : Ctrl(handler) {}
MOCK_METHOD(void, Do, (const Handler& handler), ());
// ...
void Handling()
{
if (std::shared_ptr<Handler> handlerSptr = _handler.lock())
{
try
{
Do(*handlerSptr); // mock this method to throw an exception
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
}
};
But I get the error indicating the call never happens due to function mismatch.
GMOCK WARNING:
Uninteresting mock function call - returning directly.
Function call: Action()
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect for details.
example.cpp:90: Failure
Actual function call count doesn't match EXPECT_CALL(ctrlMock, Do(HandlerMatcher(std::ref(*handlerMock))))...
Expected: to be called once
Actual: never called - unsatisfied and active
HandlerMock
is aHandler
, and_handler
does store a weak reference toHandlerMock
. Unless there's object slicing under the hood happening causing a function mismatch. Is there something I am missing here?- Not sure if MATCHER works as expected as the operator in
Handler
doesn't get invoked. - Lastly, if I remove the
operator==
fromHandler
, the MATCHER fails. Any way I could only have it inside theHandlerMock
? I want to remove since it was added solely for the test purpose.
Full code (sample)
// --------- Handler ------------
struct Handler
{
// Ideally wouldn't want to have an comparison operator within the
// main class (given it's solely for test purposes!), and rather in HandlerMock
bool operator==(const Handler& other) const
{
std::cout << "== operator called\n"; // doesn't get printed
return true;
}
virtual void Action() const = 0;
};
struct HandlerMock : public Handler
{
// bool operator==(const HandlerMock& other) const // this fails!
// {
// return true;
// }
MOCK_METHOD(void, Action, (), (const override));
};
// --------- Ctrl ------------
class Ctrl
{
std::weak_ptr<Handler> _handler;
public:
Ctrl(std::weak_ptr<Handler> handler) : _handler(handler) {}
void Handling()
{
if (std::shared_ptr<Handler> handlerSptr = _handler.lock())
{
try
{
Do(*handlerSptr); // mock this method to throw an exception
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
}
void Do(const Handler& handler) // mock this method to throw an exception
{
std::cout << ">>>> Handler.Action <<<<\n";
handler.Action(); // should not enter here since we mock'd Do() function
}
};
struct CtrlMock : public Ctrl
{
CtrlMock(std::weak_ptr<Handler> handler) : Ctrl(handler) {}
MOCK_METHOD(void, Do, (const Handler& handler), ());
};
// --------- TEST STUFF ------------
MATCHER_P(HandlerMatcher, handler, "")
{
return arg == handler;
}
ACTION(MyThrowException)
{
throw std::invalid_argument("Some exception thrown!");
}
TEST(UtClass, Test)
{
auto handlerMock = std::make_shared<HandlerMock>();
CtrlMock ctrlMock {handlerMock};
// mocking CtrlMock::Do() to throw an exception
// however the mock function call doesn't happen!
EXPECT_CALL(ctrlMock, Do(HandlerMatcher(std::ref(*handlerMock))))
.Times(1)
.WillRepeatedly(MyThrowException());
ctrlMock.Handling();
}