4

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.

簡単なテストのコードは次のとおりです。

#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;
}

IBar::~IBar() が実際に呼び出されていることをデバッガーで確認しました。しかし、まだこのエラーメッセージが表示されます。Foo::a() 内の IBar::b() への呼び出しのコメントを外すと、テストの失敗がないため、catch ステートメントは呼び出されません。IBar::~IBar() が呼び出されますが、モック オブジェクトが削除されていないことを示すエラー メッセージは表示されません。

どうもありがとうございました。

4

1 に答える 1

5

Google Mock ForDummiesthrow_on_failureで言及されているように、フラグを有効にしたために発生します。

このアプローチには問題があります。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;
}

VerifyAndClearExpectations(void*)与えられたモックの期待が満たされているかどうかをチェックします - 満たされておらず、throw_on_failureフラグが有効になっている場合、例外をスローします。

このようにして、モック オブジェクトは適切に破棄され、何か問題が発生した場合でも例外が発生します。

ところで: 使用は避けてくださいcatch (...) { }- ほとんどの場合、コードの品質が低いことがわかります。

于 2012-01-11T11:56:17.607 に答える