使用 gmock 将值设置为 void** 参数的通用自定义操作

Generic custom action to set value to void** argument using gmock

我一直在使用 gmock 测试驱动一些使用 COM 接口的代码。 Win32 函数 通过 void ** 参数使用 COM return 接口指针。嘲讽的时候 例如,对 QueryInterface 函数的调用将 return 指向 IPersistFile 的指针 界面,我执行以下操作

CPersistFileMock mockIPersistFile;
EXPECT_CALL(mockIShellLink, QueryInterface(_, _)).WillOnce(DoAll(
    SetArg1ToIPersistFile(&mockIPersistFile), Return(S_OK)));

其中 SetArg1ToIPersistFile 是这样定义的自定义操作:

ACTION_P(SetArg1ToIPersistFile, pIPersistFile) {
    *reinterpret_cast<CPersistFileMock**>(arg1) = pIPersistFile;
}

这可行,但问题是您必须为每个组合编写一个新的自定义操作 参数索引和需要通过 void ** 参数 returned 的类型。有没有办法 概括此自定义操作,以便无论类型和参数索引如何都可以应用它(到 类似于 SetArgPointee<> 但也知道类型)。

这个问题一直困扰着我们的团队,我们知道我们可以通过使用 std::get<> 来利用 args 是一个元组这一事实,但我们不知道如何传递参数索引并以通用方式键入。最后,我的一位同事想出了如何制作动作模板。这是最终实现:

ACTION_TEMPLATE(SetArgVoidPtrPtr, HAS_2_TEMPLATE_PARAMS(typename, Type, unsigned, uIndex), AND_1_VALUE_PARAMS(value))
{
    *reinterpret_cast<Type**>(std::get<uIndex>(args)) = value;
}

以及它如何在上述 IFilePersist 示例的上下文中使用:

EXPECT_CALL(mockIShellLink, QueryInterface(_, _)).WillOnce(DoAll(
    SetArgVoidPtrPtr<CPersistFileMock, 1>(&mockIPersistFile), Return(S_OK)));

请注意,这种方法可以在一般情况下使用,具有通过 void ** 个参数 return 值的函数。只是想把它放在那里,因为我没有找到太多关于这个的信息。希望这对遇到类似问题的人有所帮助。