Test a specific exception type is thrown AND the exception has the right properties

前端 未结 10 1637
梦如初夏
梦如初夏 2020-12-24 01:55

I want to test that MyException is thrown in a certain case. EXPECT_THROW is good here. But I also want to check the exception has a specific state

相关标签:
10条回答
  • 2020-12-24 02:38

    I like most of the answers. However, since it seems that GoogleTest provides EXPECT_PRED_FORMAT that helps facilitating this, I'd like to add this option to the list of answers:

    MyExceptionCreatingClass testObject; // implements TriggerMyException()
    
    EXPECT_PRED_FORMAT2(ExceptionChecker, testObject, "My_Expected_Exception_Text");
    

    where ExceptionChecker is defined as:

    testing::AssertionResult ExceptionChecker(const char* aExpr1,
                                              const char* aExpr2,
                                              MyExceptionCreatingClass& aExceptionCreatingObject,
                                              const char* aExceptionText)
    {
      try
      {
        aExceptionCreatingObject.TriggerMyException();
        // we should not get here since we expect an exception
        return testing::AssertionFailure() << "Exception '" << aExceptionText << "' is not thrown.";
      }
      catch (const MyExpectedExceptionType& e)
      {
        // expected this, but verify the exception contains the correct text
        if (strstr(e.what(), aExceptionText) == static_cast<const char*>(NULL))
        {
          return testing::AssertionFailure()
              << "Exception message is incorrect. Expected it to contain '"
              << aExceptionText << "', whereas the text is '" << e.what() << "'.\n";
        }
      }
      catch ( ... )
      {
        // we got an exception alright, but the wrong one...
        return testing::AssertionFailure() << "Exception '" << aExceptionText
        << "' not thrown with expected type 'MyExpectedExceptionType'.";
      }
      return testing::AssertionSuccess();
    }
    
    0 讨论(0)
  • 2020-12-24 02:41

    Expanding on previous answers, a macro that verifies that an exception of a given type was thrown and the message of which starts with the provided string.

    The test fails if either no exception is thrown, the exception type is wrong or if the message doesn't start with the provided string.

    #define ASSERT_THROWS_STARTS_WITH(expr, exc, msg) \
        try\
        {\
                (expr);\
                FAIL() << "Exception not thrown";\
        }\
        catch (const exc& ex)\
        {\
                EXPECT_THAT(ex.what(), StartsWith(std::string(msg)));\
        }\
        catch(...)\
        {\
                FAIL() << "Unexpected exception";\
        } 
    

    Usage example:

    ASSERT_THROWS_STARTS_WITH(foo(-2), std::invalid_argument, "Bad argument: -2");
    
    0 讨论(0)
  • 2020-12-24 02:42

    As I need to do several of such tests I wrote a macro that basically includes Mike Kinghan's answer but "removes" all the boilerplate code:

    #define ASSERT_THROW_KEEP_AS_E(statement, expected_exception) \
        std::exception_ptr _exceptionPtr; \
        try \
        { \
            (statement);\
            FAIL() << "Expected: " #statement " throws an exception of type " \
              #expected_exception ".\n  Actual: it throws nothing."; \
        } \
        catch (expected_exception const &) \
        { \
            _exceptionPtr = std::current_exception(); \
        } \
        catch (...) \
        { \
            FAIL() << "Expected: " #statement " throws an exception of type " \
              #expected_exception ".\n  Actual: it throws a different type."; \
        } \
        try \
        { \
            std::rethrow_exception(_exceptionPtr); \
        } \
        catch (expected_exception const & e)
    

    Usage:

    ASSERT_THROW_KEEP_AS_E(foo(), MyException)
    {
        ASSERT_STREQ("Cucumber overflow", e.msg());
    }
    

    Caveats:

    • As the macro defines a variable in the current scope, so it can only be used once.
    • C++11 is needed for std::exception_ptr
    0 讨论(0)
  • 2020-12-24 02:42

    I use Matthäus Brandl's macro with the following minor modification:

    Put the line

    std::exception_ptr _exceptionPtr;
    

    outside (f.e. before) the macro definition as

    static std::exception_ptr _exceptionPtr;
    

    to avoid multiple definition of the symbol _exceptionPtr.

    0 讨论(0)
提交回复
热议问题