检查该函数是否已在 gtest 中调用

Check if the function has been called in gtest

在gtest框架中,有什么方法可以检查函数是否被调用? (没有 gmock,仅使用 gtest) 例如:

class a
{
    public: 
    void dd() {...};
    void cc() {...};
    void bb() {...};
    void aa()
    {
        bb(cc(dd()));
    }
};

void main ()
{
    a dut;
    dut.aa();
}

我不关心函数输入甚至输出的正确性。 我只想知道函数(例如 aa())是否已被触发。 有什么解决办法吗?非常感谢!

without gmock, use gtest only

这是一个非常严格的限制。通常,您无法判断函数是否被调用。 Gmock 通过生成模拟函数来解决这个问题,模拟函数记录调用、参数并可以根据运行时参数伪造行为。

没有这个,你只有两个选择:

观察相关函数的副作用。

这很简单,但也很脆弱:如果您知道该函数有一个可观察到的副作用,您可以检查一下:

class a
{
public: 
    a() : aa_flag(false) {}

    void aa()
    {
        aa_flag = true;
    }

    bool aa_flag;
};

TEST(FuncCalled, CheckSideEffectFlag)
{
    a dut;
    dut.aa();
    EXPECT_TRUE(dut.aa_flag);
}

您不需要将自己局限于函数设置的标志。日志消息和其他副作用也是可行的。

class a
{
public: 
    a() : aa_flag(false) {}

    void aa()
    {
        LOG_INFO("aa called");
    }

    bool aa_flag;
};

TEST(FuncCalled, CheckSideEffectLog)
{
    a dut;
    dut.aa();
    EXPECT_TRUE(LogContains("aa called"));
}

如上所述,这是一个脆弱的解决方案,因为您可能正在检查未来随机变化的副作用。然而,有时这已经足够了。

热修补函数以跟踪调用

这很讨厌,我无法提供完整的示例,因为执行此操作的方法取决于您的编译器和目标。基本上,您指示编译器生成以一些无操作(不一定是 NOP)指令开头的函数。这允许您获取函数的地址,更改这些指令以跳转到某个地方然后返回。这非常有用,因为您可以调用一个注册了 return 地址的函数,您可以从中判断函数是否被调用。它被称为 iif aa() 的 return 地址已注册。

您将需要 OS 特定的调用来热修补您的代码,并且需要了解您正在 运行 使用的 CPU 指令。你显然失去了便携性。我也不知道你的要求,但这可能不值得。


总而言之,如果您想保持在标准范围内,最好的选择是 gmock。虚函数是动态调度的标准方式(如果你正在热修补你的图像,你就会这样做)。