【问题标题】:GMock: How to return mock class variable as the return valueGMock:如何返回模拟类变量作为返回值
【发布时间】:2015-12-08 15:42:48
【问题描述】:

我第一次尝试使用 GMock(用于 C++ 的谷歌模拟框架)。我有以下课程:

class LocalCache
{
public:
  virtual time_t GetCurrentTime() = 0;
  virtual int AddEntry(const std::string key, std::string& value);
  virtual int GetEntry(const std::string key, std::string& value);
};

GetEntry 方法调用GetCurrentTime 调用。我想模拟 GetCurrentTime 方法,以便我可以提前测试中的时钟以测试作为GetEntry 调用的一部分发生的条目的老化(请不要问我为什么老化正在完成GetEntry 通话的一部分...这是另一个讨论:( )。这是我的模拟课程:

class MockLocalCache : public LocalCache
{
public:
  using LocalCache::GetCurrentTime;
  MOCK_METHOD0(GetCurrentTime, time_t());

  MockLocalCache()
  : mCurrentTime(0)
  {
  }

  void EnableFakeTime()
  {
    ON_CALL(*this, GetCurrentTime()).WillByDefault(Return(mCurrentTime));
  }

  void SetTime(time_t now) { mCurrentTime = now; }

private:
  time_t  mCurrentTime;
};

TEST(MockTest, TimeTest)
{
  MockLocalCache mockCache;

  mockCache.EnableFakeTime();

  std::string key("mykey");
  std::string value("My Value");

  EXPECT_TRUE(mockCache.AddEntry(key, value));

  mockCache.SetTime(10);   // advance 10 seconds

  std::string expected;
  EXPECT_TRUE(mockCache.GetEntry(key, expected));
}

当我运行测试时,我希望我的模拟 GetCurrentTime 函数返回 mCurrentTime 值。但是,我得到以下错误输出:

GMOCK WARNING:
Uninteresting mock function call - taking default action specified at:
..../test_local_cache.cpp:62:
    Function call: GetCurrentTime()
          Returns: 0
Stack trace:

如果有人能告诉我我做错了什么以及如何解决它,我将不胜感激。提前致谢。

【问题讨论】:

    标签: c++ unit-testing googletest googlemock gmock


    【解决方案1】:

    您的问题的解决方案是以更简单的方式解决问题。只需在您希望调用模拟函数的地方使用 EXPECT_CALL

    class MockLocalCache : public LocalCache
    {
    public:
      MOCK_METHOD0(GetCurrentTime, time_t());
    };
    
    TEST(MockTest, TimeTest)
    {
      MockLocalCache mockCache;
    
      std::string key("mykey");
      std::string value("My Value");
    
      EXPECT_TRUE(mockCache.AddEntry(key, value));
    
      EXPECT_CALL(mockCache, GetCurrentTime()).WillOnce(Return(10));   // advance 10 seconds
    
      std::string expected;
      EXPECT_TRUE(mockCache.GetEntry(key, expected));
    }
    

    只是为了回答为什么您的示例不起作用 - 通过此调用,您的成员变量的当前值被存储 - 以后对其进行更改没有效果:

    ON_CALL(*this, GetCurrentTime()).WillByDefault(Return(mCurrentTime));
    

    查看google-mock-doc 以了解ReturnReturn(ByRef 之间的区别...

    可能 - 我没有检查这个,调用 set member value,在调用设置这个默认值之前也可以工作 - 但正如我所说 - 对于你的情况,应使用 EXPECT_CALL:

     mockCache.SetTime(10);   // advance 10 seconds
     mockCache.EnableFakeTime();
    

    【讨论】:

    • 谢谢!你的建议奏效了。首先,我用 WillRepeatedly(Return(myVariable)) 尝试了 EXPECT_CALL。我设置了我的 DoFakeTime 方法。我希望它在我的程序调用 GetCurrentTime 时返回 myVariable 值。然而,这并没有奏效。在我的每个 AddEntry/GetEntry 之前,我用 myVariable 的新值结束了调用 EXPECT_CALL。我想知道是否有办法调用 EXPECT_CALL 一次并强制它从变量中读取返回值。
    • @DnjAbc 如果您在设置 mCurrentTime 的值之前执行了WillRepeatedly 然后Return 操作存储 mCurrentTime 的当前值...您可以尝试使用Return(ByRef(mCurrentTime)) - 但可读性较差(im我的意见)而不是在每次需要时调用 ÈXPECT_CALL WillOnce ... Return...` ....
    【解决方案2】:

    仅作记录(以及未来的人会发现这个问题,比如我),而 PiotrNycz's answer 是您可以做到的最佳选择(将测试值直接保存在测试中)——在某些情况下,确实有必要从字段或变量返回“实时”返回值。

    相应的文档是here;特别是:

    • Return(field) 不起作用(它会在定义操作时复制字段的当前值)
    • Return(ByRef(field)) also 不起作用(它的作用与上述完全相同,与您的预期相反)
    • ReturnRef(field) 无法编译(因为返回类型不是引用)
    • ReturnPointee(&field) 确实工作(它返回实际调用方法时的值)

    当然,无论何时调用该方法,您都必须确保指针保持有效,因为它现在被直接使用而不是复制。

    【讨论】:

    • 谢谢,这正是我所需要的。我总是想使用Return(ByRef(foo)) 并卡住了。我希望 GTest 能抓住这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    • 2015-12-15
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多