7

Gmock フレームワークを使用して C++ で malloc をモックしたい。出来ますか?私はすべての可能な方法を試しました。しかし、この malloc 実装をホストしているクラスには、プライベート コンストラクターとデストラクターがありますか?

malloc を直接モックして NULL を返す方法はありますか?

4

3 に答える 3

1

開発者愛、

まず第一に、標準ライブラリのモックは決して良い習慣ではなく、そのような粒度レベルでコードをテストすることは芸術のための芸術です. 最初から、テストはプロジェクトの一部になることに注意する必要があります。テストを最新の状態に保ちたい場合 (つまり、作業回帰を維持する場合) は、製品コードと同じように設計を考える必要があります。実際、テストはプロジェクトの存続期間中に維持する必要があるコードでもあり、テストを読んだり、修正したり、最終的に理解したりするのに時間がかかりすぎると、そのような回帰は役に立たなくなります。「人生のドキュメンテーション」と考えてみてください。

それにもかかわらず、おそらく標準 C ライブラリをモックする最も醜い方法の 1 つは、静的フックとマクロです。次の例を検討してください。

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <boost/bind.hpp>
#include <boost/function.hpp>

static boost::function<void*(size_t)> malloc_bridge;

struct StdlibMock
{
    StdlibMock()
    {
        malloc_bridge = boost::bind(&StdlibMock::mallocMock, this, _1);
    }
    MOCK_METHOD1(mallocMock, void*(size_t));
};  // struct Struct StdlibMock

void* malloc_cheat(size_t size)
{
    return malloc_bridge(size);
}

#define malloc malloc_cheat

struct Sut
{
    void f()
    {
        malloc(10);
    }
};

struct TestWithMalloc : ::testing::Test
{
    StdlibMock stdlibMock;
};  // struct TestWithMalloc

TEST_F(TestWithMalloc, ShouldMalloc10Bytes)
{ 
    EXPECT_CALL(stdlibMock, mallocMock(10))
      .WillOnce(::testing::Return(static_cast<void*>(0)));
    Sut sut;
    sut.f();
}

#undef malloc

プリプロセッサ マクロを使用しているため、mallocMock 関数名を単純な malloc に置き換えることはできません。うまくいけば、少しは役に立ちました。

于 2013-07-15T23:06:58.170 に答える
0
  1. malloc をラップする
  2. 本番コードでテスト済みのクラス c'tor にラッパーを渡す
  3. ラッパーをモックします (ラッパーの上にインターフェイスを作成してモックすることもできます)
  4. テスト コードでモックをテスト済みのクラス c'tor に渡す

    class I_mallocWrapper
    {
        public:
        virtual ~I_mallocWrapper() {}
        virtual void* myMalloc (size_t size) = 0;
    };
    
    //wrapper to malloc
    class mallocWrapper : public I_mallocWrapper
    {
    public:
        virtual void* myMalloc (size_t size)    {return malloc(size);}
        virtual ~mallocWrapper() {}
        mallocWrapper(){}
    };
    
    //tested class with tested method that uses the wrapper
    class TestedClass
    {
    public:
        TestedClass(I_mallocWrapper* mallocW) { this->m_mallocWrapper = mallocW; }
        void testedMethod(size_t size) { m_mallocWrapper->myMalloc(size); }
        virtual ~TestedClass() {}
    private:
        I_mallocWrapper* m_mallocWrapper;
    };
    
    //production code
    void main()
    {
        size_t size = 18;
        I_mallocWrapper* MW = new mallocWrapper;
        TestedClass* TC = new TestedClass(MW);
        TC->testedMethod(size);
    }
    
    //mock the wrapper
    class mockMallocWrapper : public I_mallocWrapper
    {
    public:
       MOCK_METHOD1(myMalloc, void*(size_t size));
    };
    
    //test code
    TEST(MallocTest,callMalloc)
    {
        size_t size = 18;
        I_mallocWrapper* MW = new mockMallocWrapper;
        TestedClass* TC = new TestedClass(MW);
        TC->testedMethod(size);
    
        EXPECT_CALL(MW, myMalloc(_))
           .WillOnce(Return(NULL))
    }
    
于 2017-01-10T18:49:42.343 に答える