You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为单元测试实例化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:46:05