Reputation: 6675
Is it possible to verify the message thrown by an exception? Currently one can do:
ASSERT_THROW(statement, exception_type)
which is all fine and good but no where can I find a way to test e.what() is really what I am looking for. Is this not possible via google test?
Upvotes: 11
Views: 11909
Reputation: 2137
Something like the following will work. Just catch the exception somehow and then do EXPECT_STREQ
on the what()
call:
#include "gtest/gtest.h"
#include <exception>
class myexception: public std::exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
} myex;
TEST(except, what)
{
try {
throw myex;
FAIL(); // exception not thrown as expected
} catch (std::exception& ex) {
EXPECT_STREQ("My exception happened", ex.what());
}
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Upvotes: 4
Reputation: 5279
You can build your own assertion that allows you to make assertions on the thrown expected exception:
EXPECT_THROW
.template<typename ExceptionT, typename ActionF, typename ExceptionMatcher>
void ExpectThrowThatHelper(ActionF action, ExceptionMatcher&& exceptionMatcher)
{
try
{
action();
}
catch (const ExceptionT& e)
{
EXPECT_THAT(e, std::forward<ExceptionMatcher>(exceptionMatcher));
throw;
}
}
template<typename ExceptionT, typename ActionF, typename ExceptionMatcher>
void ExpectThrowThat(ActionF action, ExceptionMatcher&& exceptionMatcher)
{
EXPECT_THROW(ExpectThrowThatHelper<ExceptionT>(std::forward<ActionF>(action), std::forward<ExceptionMatcher>(exceptionMatcher)), ExceptionT);
}
This approach applies a matcher to the exception using EXPECT_THAT
. You could also just pass a function and call it, but since matchers can be built from lambdas, I find it more elegant to support matchers.
You can use this directly as follows:
struct GivenException final : std::exception
{
int Value = 0;
explicit GivenException(const int value)
: Value(value)
{}
[[nodiscard]] const char* what() const noexcept override
{
return "GivenException";
}
};
TEST(ExceptionInspectionTest, SomeCode_ThrowsGivenExceptionWithSpecificValue)
{
using testing::Field;
using testing::Eq;
ExpectThrowThat<GivenException>([]
{
throw GivenException(123);
}, Field(&GivenException::Value, Eq(123)));
}
If you like preprocessor macros:
#define EXPECT_THROW_THAT(ACTION, EXCEPTION, MATCHER) (ExpectThrowThat<EXCEPTION>([]{ACTION;}, (MATCHER)))
TEST(ExceptionInspectionTest, SomeCode_ThrowsGivenExceptionWithSpecificValue)
{
using testing::Field;
using testing::Eq;
EXPECT_THROW_THAT(throw GivenException(123), GivenException, Field(&GivenException::Value, Eq(123)));
}
Likewise, you can write ASSERT_THROW_THAT
, which uses ASSERT_THROW
and ASSERT_THAT
.
Upvotes: 0