Gmock フレームワークを使用して C++ で malloc をモックしたい。出来ますか?私はすべての可能な方法を試しました。しかし、この malloc 実装をホストしているクラスには、プライベート コンストラクターとデストラクターがありますか?
malloc を直接モックして NULL を返す方法はありますか?
Gmock フレームワークを使用して C++ で malloc をモックしたい。出来ますか?私はすべての可能な方法を試しました。しかし、この malloc 実装をホストしているクラスには、プライベート コンストラクターとデストラクターがありますか?
malloc を直接モックして NULL を返す方法はありますか?
開発者愛、
まず第一に、標準ライブラリのモックは決して良い習慣ではなく、そのような粒度レベルでコードをテストすることは芸術のための芸術です. 最初から、テストはプロジェクトの一部になることに注意する必要があります。テストを最新の状態に保ちたい場合 (つまり、作業回帰を維持する場合) は、製品コードと同じように設計を考える必要があります。実際、テストはプロジェクトの存続期間中に維持する必要があるコードでもあり、テストを読んだり、修正したり、最終的に理解したりするのに時間がかかりすぎると、そのような回帰は役に立たなくなります。「人生のドキュメンテーション」と考えてみてください。
それにもかかわらず、おそらく標準 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 に置き換えることはできません。うまくいけば、少しは役に立ちました。
テスト コードでモックをテスト済みのクラス 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))
}