Googlemock 在测试退出时错误地报告错误。我究竟做错了什么?

Uha*_*all 4 c++ testing googlemock

Googlemock 在测试退出时错误地报告问题。我究竟做错了什么?我已经搜索了 googlemock 文档,但没有很好的完整示例,也没有描述我遇到的问题。

我得到的错误是:

googlemocktest.cpp(53): ERROR: this mock object should be deleted but never is.
Its address is @0018FDC4.
ERROR: 1 leaked mock object found at program exit.
Run Code Online (Sandbox Code Playgroud)

简单测试的代码是:

#include <string>
#include <iostream>
#include <memory>
#include "gmock/gmock.h"

class IBar
{
public:
    virtual ~IBar() {}
    virtual void b() = 0;
    virtual int c(std::string) = 0;
};

class Foo
{
private:
    IBar *bar_;
public:
    Foo(IBar *bar);
    int a();
};

Foo::Foo(IBar *bar)
    : bar_(bar)
{
}

int Foo::a()
{
//  bar_->b();
    return bar_->c("hello");
}

class BarMock : public IBar
{
public:
    MOCK_METHOD0(b, void());
    MOCK_METHOD1(c, int(std::string));
};

using ::testing::Return;

void TestAFunctionInFoo()
{
    try
    {
        BarMock barMock;
        std::unique_ptr<Foo> newFoo(new Foo(&barMock));

        EXPECT_CALL(barMock, b());
        EXPECT_CALL(barMock, c("hello")).WillOnce(Return(42));

        newFoo->a();
    }
    catch (std::exception& e)
    {
        std::cout << "Mock exception caught: " << e.what() << std::endl;
    }
    catch (...)
    {
    }
}

int main(int argc, char* argv[])
{
    ::testing::GTEST_FLAG(throw_on_failure) = true;
    ::testing::InitGoogleMock(&argc, &argv[0]);
    TestAFunctionInFoo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我已经用调试器验证了 IBar::~IBar() 确实被调用了。但我仍然收到此错误消息。如果我在 Foo::a() 中取消对 IBar::b() 调用的注释,则不会出现测试失败,因此不会调用 catch 语句。IBar::~IBar() 被调用,但没有错误消息指示模拟对象未被删除。

非常感谢您的帮助!

小智 5

发生这种情况是因为您启用了throw_on_failure标志 - 正如Google Mock ForDummies 中提到的:

这种方法有一个问题:它有时会使 Google Mock 从模拟对象的析构函数中抛出异常。

由于从析构函数抛出异常,模拟对象永远不会被完全删除,并且在程序结束时框架会抱怨它。

解决这个问题的最简单的方法是使用 Google Test 作为单元测试框架并throw_on_failure禁用标志(默认状态)——如果模拟预期没有得到满足,GTest 会自动失败测试。

如果由于使用其他框架(例如 CppUnit)而无法使用 Google Test,则可以通过以下方式重写测试主体:

void TestAFunctionInFoo()
{
    ::testing::GTEST_FLAG(throw_on_failure) = true;
    BarMock barMock;

    try
    {
        std::unique_ptr<Foo> newFoo(new Foo(&barMock));

        EXPECT_CALL(barMock, b());
        EXPECT_CALL(barMock, c("hello")).WillOnce(Return(42));

        newFoo->a();
        ::testing::Mock::VerifyAndClearExpectations(&barMock);
    }
    catch (std::exception& e)
    {
        // expectations failed - do whatever you want 
    }

    ::testing::GTEST_FLAG(throw_on_failure) = false;
}
Run Code Online (Sandbox Code Playgroud)

VerifyAndClearExpectations(void*)检查是否满足给定的模拟期望 - 如果未满足并且throw_on_failure启用了标志,则会引发异常。

这样您的模拟对象将被正确销毁,如果出现问题,您仍然会遇到异常。

顺便说一句:避免使用catch (...) { }- 这通常是个坏主意,在大多数情况下证明代码质量很差。