c++ 使用Google Mock模拟客户端代码中复制的对象

pnwntuvh  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(158)

在这种情况下,如何模拟依赖关系?
我有一个客户端功能需要测试。它接受一个第三方API资源,并在其上调用一个方法,用输出填充其其余参数:

void ClassA::enumerateConnectedDevices(ThirdPartyAPI::BusManager & busMgr, QList<QByteArray> &devices, QStringList &descriptions)

在此函数流中的某个时刻,它调用busMgr对象,其签名如下所示:

ThirdPartyAPI::Error busMgr.GetNumOfCameras(...)

使用该调用的客户端代码如下所示:

ThirdPartyAPI::Error err = busMgr.GetNumOfCameras(&numCameras);

if (err != ThirdPartyAPI::ERROR_OK) { // compares against some enum
    cout << "Error: " << err.GetDescription();
}

我遇到的问题是从GetNumberOfCameras返回的错误复制到err局部变量。模拟BusManager和Error类可以工作到该副本生成为止。由于mock错误是ThirdPartyAPI::Error的子类,因此赋值操作符将mock切片。第三方API构造有效的错误对象并返回它们。客户端代码只能复制构造或分配它们。
我所需要做的就是从模拟的BusManager返回有效的模拟错误对象,使SUT方法可测试。只要意图保持不变,我愿意重构SUT方法。
我该怎么解决这个问题?

iibxawm4

iibxawm41#

这听起来像是在处理C中的一个经典问题:处理多态性时的切片问题。因为C在运行时并不知道你的子类,所以当你把模拟的Error对象分配给Error引用时,只有基类部分被复制(“切片”)。
一种解决方法是使用指针或智能指针而不是引用。这样,多态性就被保留了下来,并且分配了“整个”对象,而不仅仅是基类部分。
因此,如果可能的话,您可以修改您的客户端函数以使用指针,然后按预期使用多态性。
下面是一个示例,说明这可能是什么样子:

void ClassA::enumerateConnectedDevices(ThirdPartyAPI::BusManager* busMgr, QList<QByteArray> &devices, QStringList &descriptions)
{
    int numCameras = 0;
    ThirdPartyAPI::Error* err = busMgr->GetNumOfCameras(&numCameras);

    if (*err != ThirdPartyAPI::ERROR_OK) { // compares against some enum
        cout << "Error: " << err->GetDescription();
    }

    // Don't forget to delete your pointers if not using smart pointers!
    delete err;
}

这样,BusManager mock就可以返回指向mock Error的指针,并且将分配完整的mock,而不仅仅是基类部分。
如果API不允许您使用指针,并且您不能修改API,那么这可能会更具挑战性。然后,您需要找到一种方法来改变您的测试方式,或者重构代码以使其更具可测试性。例如,您可以将API调用 Package 在您自己的类的新层中,该层允许指针,并测试该层。
让我知道这是否有帮助,或者如果你需要更多的帮助!

相关问题