未调用 Gmock const 方法,而是调用原始方法

Gmock const method not called instead calling the original method

我的接口定义为 在 .h 文件中

namespace diagnostic{
class class1interface{
virtual int readpowerstate()const =0;
virtual int readparameters() = 0;
}
class class1 : public class1interface{
int readpowerstate()const;
int readparameters();}};

在 .cc 文件中我有函数

int diagnostic::readparameters(){
if(diagnostic::readpowerstate ==1)
    { //Dothis}
else
    {return 0}}

我必须执行 else 部分,因为默认情况下 if 将在我 运行 程序时被调用。所以我尝试如下使用 gmock。

class Mock_class : public diagnostic::class1interface{
public:
Mock_class(){}
MOCK_METHOD0(readparameters,int());
MOCK_CONST_METHOD0(readpowerstate,int());};

和我写的gmock测试如下 // 测试读取参数失败

TEST_F(TestBase, readParam_failure){
Mock_class mock_class;
class1 *class_dummmy = new class1();
EXPECT_CALL(mock_class, readpowerstate()).WillOnce(Return(0));
class_dummy->readparameters;
EXPECT_EQ(0, class_dummy->readparameters());}

当我执行这个程序时,我得到的错误是 错误:实际函数调用计数不匹配 EXPECT_CALL(mock_class, readpowerstate())... 预期:至少被调用一次 实际:从未致电 - 不满意且活跃

因为我是 gmock 的新手,所以解决这个问题的方法是什么。

模块测试都是关于在模拟环境中测试一个孤立的模块(如选定 class 的一个实例),特别是该模块如何与其他对象通信,以及它如何响应各种结果这些电话。为了实现这一点,可以使用 mocks 代替其他 real 对象。 Mock classes 允许:

  • 配置预期,例如,amount/sequence 调用 and/or 这些对特定函数的调用的参数值,并通过注册所有交互来验证这些;
  • 对这些预期调用的结果进行编程,这些调用的结果 return 就好像一个真实的对象执行了一些操作并对被测对象做出了响应。

这使得测试一个对象成为可能,就像它被真实的组件包围一样,而实际上没有这些组件。例如,可以测试设备管理器如何响应设备故障,方法是模拟 class 表示设备和编程,当管理器调用某些状态函数时模拟 return 错误代码。也就是说,没有使用真正的 device class,也不需要连接真正的(错误的!)device 本身并配置。模拟将假装是那个设备,重要的是,这一切都在软件层面。

然而,只有当 class 本身的设计方式允许我们以某种方式 注入 模拟对象来代替它们的真实对象时,这才有可能。最重要的是,系统中的对象需要通过接口和虚拟调用进行通信。也就是说,上述设备管理器不应与 DeviceA(具体的 class 名称)等进行通信,而是与某些 DeviceInterface 进行通信,因此 DeviceA 和新创建的模拟 DeviceMock 可以实现该接口并在该管理器中使用。这样管理器甚至不知道它正在接受测试并与模拟对象通信,而不是真正的设备包装器。

也就是说,目前,虽然您为 class1interface 创建了一个模拟,但您实际上并没有使用该模拟。相反,您尝试测试 class1。仅当您旨在测试通过 class1interface,而不是 class1 本身。

所以,有一个 class1 的模拟,你可以,例如测试 class2。但这需要这个 class 设计满足我之前提到的条件:通过接口进行通信并能够注入模拟 class.

所以要满足条件,你必须重写代码:

int class2::readdata()
{
    std::unique_ptr<diagnostic::class1interface> classint
         = std::make_unique<diagnostic::class1>();
    int value = classint->readparameters();
    return value;
}

至(这只是一个有用性有问题的例子,您必须根据自己的需要进行调整):

int class2::readdata(diagnostic::classinterface* classint)
{
    int value = classint->readparameters();
    return value;
}

因此您可以为 class2 编写测试,注入 class1:

的模拟
TEST_F( TestClass2, readParam_failure )
{
    // Mocks configuration
    Mock_class mock_class;
    EXPECT_CALL( mock_class, readparameters() ).WillOnce(Return(0));

    // System under test configuration
    diagnostic::class2 sut;

    // Test itself
    EXPECT_EQ( 0, sut.readdata(&mock_class) );
}

通过这种方式,您可以检查对 class2::readdata 的调用是否正确转发到 class1interface::readparameters,其结果是 returned。