我是gtest的初学者。我试图使用ASSERT_THROW将编译失败。任何人都可以帮忙解决这个问题:
class my_exp {};
int main(int argc, char *argv[])
{
EXPECT_THROW(throw my_exp(), my_exp); // this will pass
// This will through below compilation error
ASSERT_THROW(throw my_exp(), my_exp);
return 0;
}
编译输出:
ERROR :
In file included from /usr/include/gtest/gtest.h:57:0,
from gtest.cpp:1:
gtest.cpp: In function ‘int main(int, char**)’:
gtest.cpp:12:3: error: void value not ignored as it ought to be
ASSERT_THROW(throw my_exp(), my_exp);
^
答案 0 :(得分:7)
简短版
您以错误的方式编写测试,编写测试you should将断言置于测试(宏TEST
)或测试夹具(宏TEST_F
)。
长版
1。真正发生了什么?
要找出真正的问题并不容易,因为Google测试框架使用隐藏真实代码的宏。要在宏替换后查看代码以执行预处理,如下所示:
g++ -E main.cpp -o main.p
使用ASSERT_THROW
时的预处理结果将如下所示(格式化后):
class my_exp {};
int main(int argc, char *argv[])
{
switch (0)
case 0:
default:
if (::testing::internal::ConstCharPtr gtest_msg = "") {
bool gtest_caught_expected = false;
try {
if (::testing::internal::AlwaysTrue () ) {
throw my_exp ();
};
} catch (my_exp const &) {
gtest_caught_expected = true;
} catch (...) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws a different type.";
goto gtest_label_testthrow_7;
} if (!gtest_caught_expected) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws nothing.";
goto gtest_label_testthrow_7;
}
}
else
gtest_label_testthrow_7:
return ::testing::internal::AssertHelper (::testing::TestPartResult::kFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
return 0;
}
对于EXPECT_THROW
,结果将是相同的,除了一些差异:
else
gtest_label_testthrow_7:
::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
2。好的,找到了不同行为的原因,让我们继续。
在文件src/gtest.cc中可以找到AssertHelper
类声明,包括返回void
的赋值运算符:
void AssertHelper::operator=(const Message& message) const
现在澄清了编译器抱怨的原因。
3。但为什么导致这个问题并不清楚。尝试了解为什么ASSERT_THROW
和EXPECT_THROW
生成了不同的代码。答案是文件include/gtest/internal/gtest-internal.h
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
#define GTEST_NONFATAL_FAILURE_(message) \
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
包含致命案件的return
。
4。但现在问题为什么这个断言通常运作良好?
要回答这个问题,请尝试调查在断言进入测试时以正确方式编写的代码剪切:
#include <gtest/gtest.h>
class my_exp {};
TEST (MyExp, ThrowMyExp)
{
ASSERT_THROW (throw my_exp (), my_exp);
}
为了排除对答案的污染我只是注意到在这种情况下return
的{{1}}语句也存在,但是它放在方法中:
ASSERT_THROW
返回void MyExp_ThrowMyExp_Test::TestBody ()
!但在您的示例中,断言放在void
函数内,返回main
。看起来这是问题的根源!
尝试使用简单的代码段证明这一点:
int
5。所以最后的答案是:void f1 () {};
void f2 () {return f1();};
//int f2 () {return f1();}; // error here!
int main (int argc, char * argv [])
{
f2;
return 0;
}
宏包含表达式的return语句,其值为ASSERT_THROW
,当这样的表达式被放入函数中,返回非void值时,gcc会抱怨错误。
P.S。但无论如何我不知道为什么使用一个案例返回但是其他情况不是。
更新:我在GitHub上提出了这个问题并得到了以下答案:
ASSERT_XXX被用作穷人的例外以允许它工作 禁用例外的环境。它回报了;代替。 它意味着从返回的TEST()方法中使用 空隙强>
更新:我刚刚意识到the official documentation中描述了这个问题:
通过将其置于非空函数中,您将遇到令人困惑的编译错误&gt;喜欢&#34;错误:空值不被忽略,因为它应该是&#34;。