【问题标题】:gmock mock class does not inherit any classesgmock 模拟类不继承任何类
【发布时间】:2015-01-16 15:36:43
【问题描述】:

我看到了一些关于 gmock 的示例代码,

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <stdio.h>
#include <string>

class MockFoo {
 public:
  MockFoo() {}

  MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
  MOCK_METHOD2(Bar2, bool(int x, int y));
  MOCK_METHOD2(Bar3, void(int x, int y));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};

class GMockOutputTest : public testing::Test {
 protected:
  MockFoo foo_;
};

TEST_F(GMockOutputTest, ExpectedCall) {
  testing::GMOCK_FLAG(verbose) = "info";

  EXPECT_CALL(foo_, Bar2(0, _));
  foo_.Bar2(0, 0);  // Expected call

  testing::GMOCK_FLAG(verbose) = "warning";
}

模拟类 MockFoo 正在模拟类主体中的三个函数,但类 MockFoo 不继承任何类。

如果我理解正确的话,mock 类可以模拟虚函数和非虚函数。

1) 模拟虚函数:模拟类应该继承一个被模拟的基类,并且该类中的所有函数都应该是虚拟的,但是在这个例子中,没有基类。

2) 模拟非虚函数:模拟类不需要继承任何类,但需要在代码中添加模板才能使用高性能依赖注入。

上面的代码是否属于任何一种情况?它试图嘲笑什么?又该如何理解?

【问题讨论】:

    标签: c++ unit-testing googletest googlemock


    【解决方案1】:

    这里要记住的关键是模拟类可以覆盖超类中的虚拟或非虚拟方法,但它没有必须。有时,定义一个不符合任何特定接口或覆盖任何其他功能的完全独立的模拟是很有用的。考虑您正在测试模板化类的情况:

    template <typename T>
    class Foo {
    public:
        Foo(T* member) : _member(member) {}
    
        void f() { _member->bar(); }
    
    private:
        T* _member;
    };
    

    你想验证类Foo调用了模板参数类的bar(),但是模板类不需要符合任何形式接口;它只需要公开一个 bar() 方法。在这种情况下,您可以使用独立的模拟:

    class MockSomething {
    public:
        MOCK_METHOD0(bar, void());
    };
    

    就像你的例子一样,这个模拟类与另一个类或接口没有关系。它是一个独立的 mock,可以像使用其他任何东西一样使用它:

    TEST(StackOverflow, StandaloneMock) {
    
        MockSomething mock;
        EXPECT_CALL(mock, bar());
    
        Foo<MockSomething> foo(&mock);
        foo.f();
    }
    

    【讨论】:

      【解决方案2】:

      该代码是测试模板类NaggyMock的方法Bar2()。更准确地说,它正在测试当您使用参数00 调用方法Bar2() 时,将调用模拟中的Bar2() 方法。

      您可以将其视为静态依赖注入,因为您通过模板参数注入依赖。我会说是情况2。


      假设您的模板类 NaggyMock 看起来像这样:

      template< typename Foo >
      class NaggyMock
      {
      public:
      
          bool Bar2(int x, int y)
          {
              if ( ( 0 == x ) && ( 0 == y ) )
              {
                  return foo.Bar2( 0, 11 );
              }
      
              return false;
          }
      
      private:
      
          Foo foo;
      };
      

      然后在单元测试中,您正在测试两个参数都为 0 的情况。如果您的真实类正在使用某些资源(从网络、数据库或文件读取,...),那么要避免它,并使您的单元测试非常快,您将模拟该对象。这就是你正在做的事情。您正在注入一个模拟对象,而不是处理真实资源的类。

      欲了解更多信息,请阅读:

      【讨论】:

      • 这个mock类MockFoo没有继承任何类,如果MockFoo是mock来自NaggyMock的函数,是否应该继承NaggyMock类?
      • @ratzily No. NaggyMock 可能正在创建 MockFoo 类的对象,这是典型的依赖注入。在生产代码中,你传递了做真实事情的类——而不是模拟。
      • 好的,但此代码用于测试。我只想了解这是如何进行测试的。这个 MockFoo 正在模拟一些函数,例如 bar2()。这个 MockFoo 在嘲笑什么?模拟 NaggyMock 中定义的函数?
      猜你喜欢
      • 2011-08-08
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 2013-12-07
      • 1970-01-01
      • 2018-05-23
      相关资源
      最近更新 更多