2

我有以下免费功能信号:

ReturnT getFirstAttributeHandle(ParentHandleT a, AttributeHandleT* b);

我需要将这样一个函数的地址传递给迭代这些句柄的迭代器的构造函数。由于此函数的具体实现访问外部依赖项,我需要模拟它。

我想使用 google mock 来模拟这个函数,但我不确定如何。

这是我尝试过的:

class IAttributeIterator
{
public:
    virtual ReturnT getFirstAttributeHandle(ParentHandleT a, AttributeHandleT* b) = 0;
};

class MockAttributeIterator : public IAttributeIterator
{
public:
    MOCK_METHOD2(getFirstAttributeHandle, ReturnT(ParentHandleT a, AttributeHandleT* b));
};

然后是这样的:

MockAttributeIterator i;
AttributeIterator iter = AttributeIterator(i.getFirstAttributeHandle);
iter++;

但这不会编译,给出错误:

'MockAttributeIterator::getAttribute':函数调用缺少参数列表;使用 '&MockAttributeIterator::getAttribute' 创建指向成员的指针

关于我如何做到这一点的任何建议?

4

3 回答 3

2

不,您不能将指向成员函数的指针转换为函数指针(这就是编译器所说的)。

如果 AttributeIterator 的构造函数接受指向函数的指针,那么您需要创建一个伪函数,该函数调用 MockAttributeIterator 上的 getFirstAttributeHandle 方法。像这样的东西:

namespace
{
    MockAttributeIterator mockObj;
    ReturnT FakeHandle(ParentHandleT a, AttributeHandleT* b)
    {
      mockObj.getFirstAttributeHandle( a, b );
    }
}

并将指向 FakeHandle 的指针传递给 AttributeIterator 的构造函数。

顺便说一句,我刚刚检查了 gmock 常见问题解答,甚至在那里进行了解释(这里是链接)。

有几件事:

  • 上面贴的代码最好放在匿名命名空间中
  • 要清除测试之间的期望,在您的设置方法中(每个单元测试框架都有一个),请执行以下操作:

    void setUp()
    {
      ::testing::Mock::VerifyAndClearExpectations( &mockObj ):
    }
    
于 2012-07-02T10:21:02.337 回答
1

该问题与 google mock 完全无关,编译器抱怨以下语句:

AttributeIterator iter = AttributeIterator(i.getFirstAttributeHandle);

注意表达式 as i.getFirstAttributeHandle,它是一个成员函数调用,所以编译器试图匹配函数签名并没有得到任何结果。

如果您想将部分应用的函数安全地传递给另一个类,请尝试boost.function/bind使用原始函数指针,这是非常危险且容易出错的。

于 2014-02-20T09:24:48.347 回答
0

您可以将自由函数封装在代理类中,然后模拟对代理方法的调用。以下代码概述了如何在代码中模拟CreateFileWCloseHandle调用。

gmock Cookbook中也概述了基本思想。

/// Common Interface
class IWindows
{
public:
    virtual HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
        DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) = 0;
    virtual BOOL CloseHandle(HANDLE hObject) = 0;
};


/// Implementation
class WindowsWrapper : public IWindows
{
public:
    WindowsWrapper(void);
    virtual ~WindowsWrapper(void);
    virtual HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
        DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
    virtual BOOL CloseHandle(HANDLE hObject);
};

/// Mock
class MockWindowsWrapper : public IWindows
{
public:
    MockWindowsWrapper() {}
    virtual ~MockWindowsWrapper() {}
    MOCK_METHOD7(CreateFileW, HANDLE(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
        DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile))`
    {
        return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    }
    MOCK_METHOD1(CloseHandle, BOOL(HANDLE hObject))
    {
        return ::CloseHandle(hObject);
    }
};
于 2013-06-05T06:57:00.257 回答