2012-04-23 11 views
21

私はテストのためにGoogleMock/GoogleTestを使いました。マッチャーがmockにshared_ptrをパラメータとして持っていて、同じshared_ptrでEXPECTが呼び出されたときに、いくつかの奇妙な動作が見られました。コードの問題ピース:GoogleMockでshared_ptrが漏れているのはなぜですか?

#include <gmock/gmock.h> 
#include <gtest/gtest.h> 

#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 
using namespace boost; 
using namespace testing; 

struct MyParameter 
{ 
    virtual ~MyParameter() {} 
    virtual void myMethod() = 0; 
}; 

struct MyParameterMock : public MyParameter 
{ 
    MOCK_METHOD0(myMethod, void()); 
}; 

struct MyClass 
{ 
    virtual ~MyClass() {} 
    virtual void myMethod(shared_ptr<MyParameter> p) {} 
}; 

struct MyClassMock : public MyClass 
{ 
    MOCK_METHOD1(myMethod, void(shared_ptr<MyParameter>)); 
}; 

TEST(LeakTest, GoogleMockLeaksMatchedPointer) 
{ 
    shared_ptr<MyClassMock> c = make_shared<MyClassMock>(); 
    shared_ptr<MyParameterMock> p = make_shared<MyParameterMock>(); 
    { 
     InSequence dummy; 
     EXPECT_CALL(*c, myMethod(Eq(p))); 
     EXPECT_CALL(*p, myMethod()); 
    } 
    c->myMethod(p); 
    p->myMethod(); 
} 

このテストを実行すると、私は

leak_ptr_mock.cpp:37: ERROR: this mock object (used in test LeakTest.GoogleMockLeaksMatchedPointer) should be deleted but never is. Its address is @0x9309544. 
ERROR: 1 leaked mock object found at program exit. 

これがなぜ起こるかのいずれかのアイデアを得ますか?私はむしろMock::AllowLeakを使用する必要はありません。

答えて

26

これはをとし、期待値を宣言した順番を使用してshared_ptrとした結果です。

あなたはpuse_countを高める

EXPECT_CALL(*c, myMethod(Eq(p))); 

を呼び出します。リーク検出に合格するには、TESTの末尾(またはその前)にpを破壊する必要があります。

ここでの問題は、gmockが内部的に、前の期待値へのポインタを保持することによって必要なモック呼び出しシーケンスのレコードを保持することです。だからEXPECT_CALL(*p, myMethod());に電話すると、それは以前の期待値へのポインタのコピーを取得します。

TESTが終了すると、pのデストラクタへの呼び出しをブロックするという効果があります。

これを回避するために、私はあなたの最善の策は、あなたがTESTを終了する直前に

EXPECT_TRUE(Mock::VerifyAndClearExpectations(p.get())); 

を呼び出すことだと思います。これにより、pの期待値がクリアされます。これには、前提条件の期待値が批判的に含まれており、pのデストラクタを正しく呼び出すことができます。

また、モックコールの順序が重要でない場合は、InSequence dummy;を単に削除すると、pのデストラクタも実行できます。


脇に、コードにはいくつかの問題があります。

  • あなたの基本構造体は、それが
  • p->myMethod(p);それは、フレイザー作品p->myMethod();
+0

でなければなりませんgmockの機能をオーバーライドすることを可能にするために仮想なければなりません仮想デストラクタ

  • MyClass::myMethodを持っている必要があります!あなたの提案に従ってコードを修正しました。 –

  • +0

    @ bruno nery:どのバージョンのGoogleMockを使用していますか? –

    +0

    pがcより前に作成されるとどうなりますか?最終的に破壊されるよりも、その期待が検証され、クリアされて、pの参照カウンターを減少させるであろう。その後、カウンタは0になっているので、pは破壊され、検証され、完全に破壊されます。 –

    関連する問題