ASSERT_THROW:错误:无法忽略void值,因为它应该是

时间:2016-01-09 17:14:36

标签: googletest

我是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); 
    ^

1 个答案:

答案 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_THROWEXPECT_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;。