代码之家  ›  专栏  ›  技术社区  ›  pptaszni

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

  •  2
  • pptaszni  · 技术社区  · 2 年前

    我有一个运行异步网络工作程序的系统,它会定期检查工作程序是否有 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 包含指向可以重新抛出的自定义异常的指针?

    2 回复  |  直到 2 年前
        1
  •  5
  •   HolyBlackCat    2 年前

    std::make_exception_ptr :

    std::exception_ptr e = std::make_exception_ptr(MyException{});
    
        2
  •  0
  •   pptaszni    2 年前

    最后,事情变得很简单。在测试设置中,您可以在 try 块,然后抓住它,存储 std::exception_ptr ,并在gmock操作中使用它:

    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);
    }
    

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