简体   繁体   English

依赖注入的实际例子和 mocking with Googlemock

[英]Practical example for Dependency Injection and mocking with Googlemock

I'm looking for a simple complete cut and paste example for Dependency Injection and mocking using Googlemock.我正在寻找一个简单的完整剪切和粘贴示例,用于依赖注入和 mocking 使用 Googlemock。 I have found several theoretical discussion about the issue with code snippets that explains how it works but wasn't able to find a complete running example to cut and paste and try.我发现了几个关于这个问题的理论讨论,这些讨论用代码片段解释了它是如何工作的,但无法找到一个完整的运行示例来剪切和粘贴并尝试。 Is there something available?有什么可用的吗?

To understand how it works with Googlemock I have made this complete example that I would like to share with other beginners to the topic.为了了解它如何与 Googlemock 一起工作,我制作了这个完整的示例,我想与其他初学者分享该主题。 According to other Q&A theoretical background is assumed.根据其他问答理论背景假设。 I run it on a Debian Bullseye system.我在 Debian Bullseye 系统上运行它。

There is a class Mylib in a fictional library that method just returns 123 .在一个虚构的库中有一个 class Mylib ,该方法只返回123 Under test it is mocked to return 456 .在测试中,它被模拟返回456 The real class and the mocking class are both inherit from an interface class.真正的 class 和 mocking class 都继承自一个接口 ZA2F2ED4F8EBC2CBB4C21A29DC40AB6DZ。 This ensures that the different objects that are injected by the injector ( TEST(..){..} macro) to the application Myapp , have the same method calls.这确保了由注入器( TEST(..){..}宏)注入到应用程序Myapp的不同对象具有相同的方法调用。 Here is the example:这是示例:

~$ cat test_myapp.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <iostream>

class MylibInterface {
public:
    virtual ~MylibInterface() {}
    virtual int func() = 0;
};


class Mylib : public MylibInterface {
public:
    virtual ~Mylib() {}
    int func() override {
        return 123;
    }
};


class MylibMock : public MylibInterface {
public:
    virtual ~MylibMock() {}
    MOCK_METHOD(int, func, (), (override));
};


class Myapp {
    // this pointer will be injected by the injector either with pointing
    // to the real object or to the mock object. The interface ensures that both
    // objects have the same method calls.
    MylibInterface* m_mylib;

public:
    Myapp(MylibInterface* mylib) : m_mylib(mylib) {}

    bool func() {
        int ret = m_mylib->func();
        std::cout << "mylib.func returns: '" << ret << "'\n";
        return true;
    }
};


TEST(MylibTestSuite, mock_mylib_func)
// this test macro can be seen as the injector. It determins what object
// is injected to myapp.
{
    using ::testing::Return;

    // inject a real mylib object to myapp and exersize it
    Mylib mylib;
    Myapp myapp(&mylib);
    std::cout << "  real ";
    EXPECT_TRUE(myapp.func());

    // inject a mocked mylib object to myapp
    MylibMock mylib_mock;
    Myapp myapp_mock(&mylib_mock);
    EXPECT_CALL(mylib_mock, func())
        .WillOnce(Return(456));

    // and exersize it
    std::cout << "mocked ";
    EXPECT_TRUE(myapp_mock.func());
}


int main(int argc, char** argv) {
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

I compiled it with:我编译它:

~$ /usr/bin/g++ -std=c++11 -pedantic-errors -Wall -o test_myapp.a -I$BUILD_DIR/googletest-src/googletest/include -I$BUILD_DIR/googletest-src/googlemock/include test_myapp.cpp $BUILD_DIR/lib/libgtestd.a $BUILD_DIR/lib/libgmockd.a -lpthread

When executing the test it should look like this:执行测试时,它应该如下所示:

~$ ./test_myapp.a
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MylibTestSuite
[ RUN      ] MylibTestSuite.mock_mylib_func
  real mylib.func returns: '123'
mocked mylib.func returns: '456'
[       OK ] MylibTestSuite.mock_mylib_func (0 ms)
[----------] 1 test from MylibTestSuite (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

Ingo's example using std::shared_ptr. Ingo 的示例使用 std::shared_ptr。

// Ingo's answer to Dependency Injection and mocking modified to
// use std::shared_ptr.

#include <iostream>
#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

class MylibInterface {
 public:
  virtual ~MylibInterface() {}
  virtual int func() = 0;
};

class Mylib : public MylibInterface {
 public:
  virtual ~Mylib() {}
  int func() override {
    return 123;
  }
};

using MyLibPtr = std::shared_ptr<MylibInterface>;

class MylibMock : public MylibInterface {
 public:
  virtual ~MylibMock() {}
  MOCK_METHOD(int, func, (), (override));
};

class Myapp {
  // this pointer will be injected by the injector either with pointing
  // to the real object or to the mock object. The interface ensures that both
  // objects have the same method calls.
  // MylibInterface* m_mylib;
  MyLibPtr m_mylib;

 public:
  Myapp(MyLibPtr mylib) : m_mylib(mylib) {}
  bool func() {
    int ret = m_mylib->func();
    std::cout << "mylib.func returns: '" << ret << "'\n";
    return true;
  }
};

TEST(MylibTestSuite, mock_mylib_func)
// this test macro can be seen as the injector. It determins what object
// is injected to myapp.
{
  using ::testing::Return;

  // inject a real mylib object to myapp and exersize it
  Myapp myapp(std::make_shared<Mylib>());
  std::cout << "  real ";
  EXPECT_TRUE(myapp.func());

  // inject a mocked mylib object to myapp
  //MylibMock mylib_mock;
  auto lp = std::make_shared<MylibMock>();
  Myapp myapp_mock( lp );

  //EXPECT_CALL(mylib_mock, func())
  EXPECT_CALL( *lp, func())
      .WillOnce(Return(456));

  // and exersize it
  std::cout << "mocked ";
  EXPECT_TRUE(myapp_mock.func());
}
/*
int main(int argc, char** argv) {
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}
*/`

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM