c++ 依赖注入和Googlemock模拟的实际示例

ymdaylpp  于 2022-11-19  发布在  Go
关注(0)|答案(2)|浏览(171)

我正在寻找一个简单完整的剪切和粘贴依赖注入和模仿使用Googlemock的例子。我已经找到了几个理论上的讨论与代码片段的问题,解释了它是如何工作的,但不能找到一个完整的运行例子剪切和粘贴和尝试。有什么可用的?

hs1rzwqc

hs1rzwqc1#

为了了解它如何与Googlemock一起工作,我做了这个完整的例子,我想与其他初学者分享这个主题。根据其他问答理论背景假设。我在Debian Bullseye系统上运行它。
在一个虚构的库中有一个类Mylib,该方法只返回123。在测试中,它被模拟为返回456。真实的类和模拟类都继承自一个接口类。这确保了注入器注入的不同对象(TEST(..){..}宏)到应用程序Myapp,都有相同的方法调用.下面是例子:

~$ 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();
}

我把它编译成:

~$ /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

执行测试时,它应该如下所示:

~$ ./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.
pvabu6sv

pvabu6sv2#

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();
}
*/`

相关问题