我在工作中使用 googlemock。我们经常使用 EXPECT_THROW、EXPECT_NO_THROW 等...
我的问题是,当函数包装在 EXPECT_NO_THROW 中但实际上引发异常(即代码错误)时,如何让 googlemock 输出异常详细信息以及堆栈跟踪?
我得到的唯一输出是它引发了异常并且测试失败......这对于调试根本原因没有用。
我在工作中使用 googlemock。我们经常使用 EXPECT_THROW、EXPECT_NO_THROW 等...
我的问题是,当函数包装在 EXPECT_NO_THROW 中但实际上引发异常(即代码错误)时,如何让 googlemock 输出异常详细信息以及堆栈跟踪?
我得到的唯一输出是它引发了异常并且测试失败......这对于调试根本原因没有用。
EXPECT_THROW
,EXPECT_NO_THROW
等确实是Google Test的一部分,而不是 Google Mock。
除了破解 gtest 源之外,我不知道有任何方法可以获取有关异常的更多信息。仅对于std::exception
s,以下更改至少应在a或失败what()
时输出异常。EXPECT_NO_THROW
ASSERT_NO_THROW
在 gtest/include/gtest/internal/gtest-internal.h 中,在第 1140 行附近,将GTEST_TEST_NO_THROW_
宏更改为:
#define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (...) { \
try { \
std::exception_ptr exceptn_ptr(std::current_exception()); \
std::rethrow_exception(exceptn_ptr); \
} catch(const std::exception& exceptn) { \
std::cerr << exceptn.what() << '\n'; \
} \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
fail("Expected: " #statement " doesn't throw an exception.\n" \
" Actual: it throws.")
您显然可以在这里添加更多功能;捕获自定义异常类型,格式化失败消息以包含异常信息等。
您也可以一起省略断言,让您的测试用例抛出异常。因此,与其断言f()
不会抛出:
ASSERT_NO_THROW(f());
您只需调用该函数:
f();
如果它抛出一个异常,它会给你一个像这样的输出:
C++ exception with description "something broke in f()" thrown in the test body.
这当然只适用于ASSERT_NO_THROW
,因为测试用例将终止。
一般来说,GMock/GTest 无法对捕获的对象做任何事情。它不能仅仅假设你的代码抛出了std::exception
你想要的尽可能多的子类,并且 C++ 不提供在引发异常时保存堆栈跟踪的任何方法,即使实际上存在堆栈帧和调试符号在你的二进制文件中。
但是,单元测试确实是一种验证技术,其他工具必须是您诊断的朋友。无论是添加临时日志记录(例如printf
)还是交互式调试器(例如 ) gdb
,都有更好的工具来完成这项工作。
我发现在单元测试二进制文件上运行 gdb 是最简单的。幸运的是,我们编译了所有启用调试的代码 =]。