我想模拟下面的方法Ctrl::Do(const Handler& handler)
抛出一个异常。Ctrl
存储指向Handler
的弱指针
class Ctrl
{
std::weak_ptr<Handler> _handler;
// ...
};
的引用传递给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;
}
}
}
};
但我得到错误,表明由于函数不匹配,调用从未发生。
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
,并且_handler
确实存储了对HandlerMock
的弱引用。除非在引擎盖下发生了对象切片,导致函数不匹配。这里是否遗漏了什么?- 不确定MATCHER是否按预期工作,因为
Handler
中的运算符未被调用。 - 最后,如果我从
Handler
中删除operator==
,MATCHER将失败。我是否可以将其仅放在HandlerMock
中?我希望删除它,因为添加它只是为了测试目的。
完整代码(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();
}
1条答案
按热度按时间w80xi6nr1#
您需要将
Ctrl::Do()
标记为virtual
,这样当Ctrl::Handling()
调用Ctrl::Do()
时,它实际上会调用CtrlMock::Do()
。关于
operator==
:这取决于你想做什么。从代码中我猜你真正想要的是通过地址匹配handlerMock
。为此,你可以简单地使用testing::Ref
:并且完全删除
HandlerMatcher
。完整的例子是godbolt。否则,如果你不想比较地址,而是想比较对象的值,我认为不能比较Handler
而可以比较HandlerMock
会很奇怪;也就是说,乍看起来,将operator==
与Handler
结合起来确实有意义。当然,在任何情况下,您都可以在测试代码中定义比较operator==
outside ofHandler
。