如何为单元测试实例化std::exception_ptr以模拟异常场景
如何模拟返回含自定义异常的
std::exception_ptr? 问题场景
我有一套运行异步网络worker的系统,系统会定期检查worker是否存储了std::exception_ptr,若存在则抛出异常或报告错误。简化的系统和Mock代码如下:
#include <exception> #include <gmock/gmock.h> // 简化的Network接口及Mock实现 struct INetwork { virtual std::exception_ptr getExceptionPtr() const = 0; }; struct MockedNetwork: public INetwork { public: MOCK_METHOD(std::exception_ptr, getExceptionPtr, (), (const override)); }; // 简化的系统类 class System { public: System(INetwork& network): _network{network} {} void run() { // 复杂逻辑省略 std::exception_ptr exPtr = _network.getExceptionPtr(); if (exPtr) { std::rethrow_exception(exPtr); } } private: INetwork& _network; };
需要测试的场景:
当Network通过exception_ptr报告错误时,System必须重新抛出该异常
我尝试编写的测试用例无法正确生成含自定义异常的std::exception_ptr:
#include <stdexcept> #include <gtest/gtest.h> struct MyException: public std::runtime_error { MyException(): std::runtime_error("MyException") {} }; TEST(Demo, demo) { MockedNetwork mockedNet; EXPECT_CALL(mockedNet, getExceptionPtr()).WillRepeatedly([]() -> std::exception_ptr{ return nullptr; // 这是无错误场景,不是我需要的 // return new MyException; // 编译不通过,写法也不对 }); System sut(mockedNet); ASSERT_THROW(sut.run(), MyException); }
解决方案
要生成包含自定义异常的std::exception_ptr,有两种标准写法:
- 使用
std::make_exception_ptr直接构造,这是最简洁的方式 - 在
try块中抛出异常,然后用std::current_exception()捕获并保存
修改后的测试用例(推荐写法)
#include <stdexcept> #include <gtest/gtest.h> #include <exception> struct MyException: public std::runtime_error { MyException(): std::runtime_error("MyException") {} }; TEST(Demo, demo) { MockedNetwork mockedNet; // 使用std::make_exception_ptr生成含自定义异常的exception_ptr EXPECT_CALL(mockedNet, getExceptionPtr()) .WillRepeatedly([]() -> std::exception_ptr { return std::make_exception_ptr(MyException()); }); System sut(mockedNet); // 验证System确实重新抛出了MyException ASSERT_THROW(sut.run(), MyException); }
替代写法(模拟实际捕获异常场景)
如果需要模拟真实代码中捕获异常并生成exception_ptr的逻辑,可以用这种方式:
EXPECT_CALL(mockedNet, getExceptionPtr()) .WillRepeatedly([]() -> std::exception_ptr { try { throw MyException(); } catch (...) { return std::current_exception(); } });
两种方式都能生成可被std::rethrow_exception重新抛出的有效std::exception_ptr,优先推荐std::make_exception_ptr,代码更简洁直观。
内容的提问来源于stack exchange,提问作者pptaszni
相关产品推荐
相关产品推荐

