7

我想使用 Gmock 框架在 C++ 中模拟 malloc。可能吗?我已经尝试了所有可能的方法。但是托管这个 malloc 实现的类有一个私有构造函数和析构函数?

有什么方法可以直接模拟 malloc 以返回 NULL?

4

3 回答 3

1

开发者爱,

首先,模拟标准库从来都不是一个好的做法,在这种粒度级别上测试代码是为艺术而艺术。您必须注意到,从一开始,测试就成为项目的一部分,如果您想让它们保持最新(也就是维护工作回归),您必须以与生产代码相同的方式考虑它们的设计。事实上,测试也是在项目生命周期中必须维护的代码,如果阅读、纠正和最终理解测试将花费太多时间,那么这种回归将毫无用处。尝试将其视为“生活文档”。

然而,模拟标准 C 库的最丑陋的方法之一可能是静态钩子和宏。考虑以下示例:

#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

请注意,由于使用了预处理器宏,您不能用简单的 malloc 替换 mallocMock 函数名称。希望对您有所帮助。

于 2013-07-15T23:06:58.170 回答
0

glibcmock可以帮助你模拟 malloc 和其他 libc 函数。

#include "got_hook.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include <mutex>
#include <memory>

struct MockMalloc {
    MOCK_METHOD1(Malloc, void *(size_t));
};

static MockMalloc *g_mock{nullptr};

static void *Malloc(size_t size) {
    return g_mock->Malloc(size);
}

static std::mutex g_test_mutex;

TEST(MallocTest, ReturnNull) {
    std::lock_guard<std::mutex> lock(g_test_mutex);
    std::unique_ptr<MockMalloc> mock(g_mock = new MockMalloc());
    testing::GotHook got_hook;
    ASSERT_NO_FATAL_FAILURE(got_hook.MockFunction("malloc", (void*)&Malloc););
    // ... do your test here, for example:
    EXPECT_CALL(*g_mock, Malloc(testing::_)).WillOnce(testing::Return(nullptr));
    EXPECT_EQ(nullptr, malloc(1));
}
于 2017-03-12T01:26:37.360 回答
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 回答