DeveloperLove,
first of all, mocking a standard library is never a good practice, and testing code at this level of granulation is an art for art's sake. You should note that from the very beginning, tests become part of the project, and if you want to keep them up to date (aka maininging working regression), you should think of their design in the same way as production code. In fact, tests are also code that must be maintained throughout the life of the project, and when reading, fixing, and finalizing, when the tests take too long, such a regression will be useless. Try to think of it as "documentation for life."
However, probably one of the ugliest ways to mock the standard C library is with a static hook and macros. Consider the following example:
#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
Note that you cannot replace the mallocMock function name with a simple malloc due to the use of a preprocessor macro. Hope it was a little helpful.
source share