如何实例化 std::exception_ptr 用于单元测试目的

How to instantiate std::exception_ptr for unit testing purpose

提问人:pptaszni 提问时间:11/16/2023 更新时间:11/17/2023 访问量:50

问:

我有运行异步网络工作器的系统,并定期检查工作器是否存储了一些。在这种情况下,它可能会以其他方式引发或报告错误。简单示例:std::exception_ptr

#include <exception>
#include <gmock/gmock.h>

// simplified Network interface and the mock
struct INetwork {
    virtual std::exception_ptr getExceptionPtr() const = 0;
};
struct MockedNetwork: public INetwork {
public:
    MOCK_METHOD(std::exception_ptr, getExceptionPtr, (), (const override));
};
// simplified system
class System {
public:
    System(INetwork& network): _network{network} {}
    void run() {
        // some complex logic
        std::exception_ptr exPtr = _network.getExceptionPtr();
        if (exPtr) {
            // error handling, or just rethrow
            std::rethrow_exception(exPtr);
        }
    }
private:
    INetwork& _network;
};

然后,我想针对以下方案测试我的代码

每当网络通过exception_ptr报告错误时,系统将重新抛出此异常

所以我有这个小的 gtest 测试用例:

#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;  // this is OK, but I want to simulate an error, not error-free run
        // return new MyException;  // this doesn't compile, and anyway seems like a bad idea
    });
    System sut(mockedNet);
    ASSERT_THROW(sut.run(), MyException);
}

如何模拟模拟网络返回包含指向可重新引发的自定义异常的指针的情况?std::exception_ptr

C++ 异常 GoogleTest

评论


答:

0赞 pptaszni 11/16/2023 #1

最后,结果很简单。在测试设置中,您只需在块内抛出一个异常,然后捕获它,存储 ,并在 gmock 操作中使用它:trystd::exception_ptr

TEST(Demo, demo) {
    MockedNetwork mockedNet;
    std::exception_ptr ptr;
    try {
        throw MyException();
    } catch(const std::exception&) {
        ptr = std::current_exception();
    }
    EXPECT_CALL(mockedNet, getExceptionPtr()).WillRepeatedly([ptr]() -> std::exception_ptr{
        return ptr;
    });
    System sut(mockedNet);
    ASSERT_THROW(sut.run(), MyException);
}

这可行,但也许还有其他更好和/或更有趣的方法来达到相同的效果。

5赞 HolyBlackCat 11/17/2023 #2

标准::make_exception_ptr

std::exception_ptr e = std::make_exception_ptr(MyException{});

评论

0赞 pptaszni 11/17/2023
哇,我不知道我怎么可能在 cppreference 中没有看到它......现在我觉得自己很傻。但是谢谢!