2

次の無料関数 sig があります。

ReturnT getFirstAttributeHandle(ParentHandleT a, AttributeHandleT* b);

このような関数のアドレスを、これらのハンドルを反復処理する反復子のコンストラクターに渡す必要があります。この関数の具体的な実装は外部の依存関係にアクセスするため、それをモックする必要があります。

Google モックを使用してこの関数をモックしたいのですが、方法がわかりません。

これは私が試したものです:

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のよくある質問をチェックしました、そしてこれはそこでさえ説明されます(ここにリンクがあります)。

いくつかあります:

  • 上記のコードは、匿名の名前空間に配置するのが最適です
  • テスト間の期待をクリアするには、セットアップ方法(すべての単体テストフレームワークに1つあります)で、次のようにします。

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

この問題は Google モックとはまったく関係ありません。コンパイラは次のステートメントについて不平を言っていました。

AttributeIterator iter = AttributeIterator(i.getFirstAttributeHandle);

メンバー関数 calli.getFirstAttributeHandleであるas 式に注意してください。そのため、コンパイラは関数シグネチャと一致させようとしましたが、何も得られませんでした。

部分的に適用された関数を別のクラスに安全に渡したい場合は、boost.function/bind代わりに with を試してください。生の関数ポインターをいじるのは非常に危険で、エラーが発生しやすくなります。

于 2014-02-20T09:24:48.347 に答える
0

free 関数をプロキシ クラスにカプセル化してから、プロキシ メソッドの呼び出しをモックできます。次のコードは、コード内でモック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 に答える