google mock分享(全网最全最好的gmock文档,没有之一)

转载
  1. EXPECT_CALL(mockFoo, getValue()).WillOnce(Return(string("Hello World")));
对于这样的期望行为的定义,我何时调用mockFoo.getValue()或者何时mockFoo.getSize()都可以的。

但有时候我们需要定义有序的(Ordered)的调用方式,即序列 (Sequences) 指定预期的顺序. 在同一序列里的所有预期调用必须按它们指定的顺序发生; 反之则可以是任意顺序.


  1. using ::testing::Return;
  2. using ::testing::Sequence;
  3. int main(int argc, char **argv) {
  4. ::testing::InitGoogleMock(&argc, argv);
  5. Sequence s1, s2;
  6. MockFoo mockFoo;
  7. EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2).WillOnce(Return(1));
  8. EXPECT_CALL(mockFoo, getValue()).InSequence(s1).WillOnce(Return(
  9. string("Hello World!")));
  10. cout << "First:\t" << mockFoo.getSize() << endl;
  11. cout << "Second:\t" << mockFoo.getValue() << endl;
  12. return EXIT_SUCCESS;
  13. }
  • 首先在第8行建立两个序列:s1、s2。
  • 然后在第11行中,EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2)说明getSize()的行为优先于s1、s2.
  • 而第12行时,EXPECT_CALL(mockFoo, getValue()).InSequence(s1)说明getValue()的行为在序列s1中。

得到的结果如下:

First: 1
Second: Hello World!

当我尝试一下把mockFoo.getSize()mockFoo.getValue()的调用对调时试试:


  1. cout << "Second:\t" << mockFoo.getValue() << endl;
  2. cout << "First:\t" << mockFoo.getSize() << endl;
得到如下的错误信息:

unknown file: Failure

Unexpected mock function call &ndash; returning default value.
Function call: getValue()
Returns: ""
Google Mock tried the following 1 expectation, but it didn't match:

FooMain.cc:29: EXPECT_CALL(mockFoo, getValue())…
Expected: all pre-requisites are satisfied
Actual: the following immediate pre-requisites are not satisfied:
FooMain.cc:28: pre-requisite #0
(end of pre-requisites)
Expected: to be called once
Actual: never called &ndash; unsatisfied and active
Second:
First: 1
FooMain.cc:29: Failure
Actual function call count doesn't match EXPECT_CALL(mockFoo, getValue())…
Expected: to be called once
Actual: never called &ndash; unsatisfied and active

另外,我们还有一个偷懒的方法,就是不要这么傻乎乎地定义这些个Sequence s1, s2的序列,而根据我定义期望行为(EXPECT_CALL)的顺序而自动地识别调用顺序,这种方式可能更为地通用。


  1. using ::testing::InSequence;
  2. using ::testing::Return;
  3. int main(int argc, char **argv) {
  4. ::testing::InitGoogleMock(&argc, argv);
  5. InSequence dummy;
  6. MockFoo mockFoo;
  7. EXPECT_CALL(mockFoo, getSize()).WillOnce(Return(1));
  8. EXPECT_CALL(mockFoo, getValue()).WillOnce(Return(string("Hello World")));
  9. cout << "First:\t" << mockFoo.getSize() << endl;
  10. cout << "Second:\t" << mockFoo.getValue() << endl;
  11. return EXIT_SUCCESS;
  12. }

Mock实践

下面我从我在工作中参与的项目中选取了一个实际的例子来实践Mock。
这个例子的背景是用于搜索引擎的:

由于Google Mock不能Mock模版方法,因此我稍微更改了一下原本的接口,以便演示:

我改过的例子

我们先来看看引擎定义好的接口们:
VariantField.h 一个联合体,用于保存Query中的Segment的值


  1. #ifndef VARIANTFIELD_H_
  2. #define VARIANTFIELD_H_
  3. #include <boost/cstdint.hpp>
  4. namespace seamless {
  5. union VariantField
  6. {
  7. const char * strVal;
  8. int32_t intVal;
  9. };
  10. } // namespace mlr_isearch_api
  11. #endif // VARIANTFIELD_H_

IParameterInterface.h 提供一个接口,用于得到Query中的各个Segment的值


  1. #ifndef IPARAMETERINTERFACE_H_
  2. #define IPARAMETERINTERFACE_H_
  3. #include <boost/cstdint.hpp>
  4. #include "VariantField.h"
  5. namespace seamless {
  6. class IParameterInterface {
  7. public:
  8. virtual ~IParameterInterface() {};
  9. public:
  10. virtual int32_t getParameter(const char* name, VariantField*& value) = 0;
  11. };
  12. } // namespace
  13. #endif // IPARAMETERINTERFACE_H_

IAPIProviderInterface.h 一个统一的外部接口


  1. #ifndef IAPIPROVIDERINTERFACE_H_
  2. #define IAPIPROVIDERINTERFACE_H_
  3. #include <boost/cstdint.hpp>
  4. #include "IParameterInterface.h"
  5. #include "VariantField.h"
  6. namespace seamless {
  7. class IAPIProviderInterface {
  8. public:
  9. IAPIProviderInterface() {}
  10. virtual ~IAPIProviderInterface() {}
  11. public:
  12. virtual IParameterInterface* getParameterInterface() = 0;
  13. };
  14. }
  15. #endif // IAPIPROVIDERINTERFACE_H_

引擎定义好的接口就以上三个,下面是引擎中的一个模块用于根据Query中的Segment接合业务处理的。Rank.h 头文件


  1. #ifndef RANK_H_
  2. #define RANK_H_
  3. #include "IAPIProviderInterface.h"
  4. namespace seamless {
  5. class Rank {
  6. public:
  7. virtual ~Rank() {}
  8. public:
  9. void processQuery(IAPIProviderInterface* iAPIProvider);
  10. };
  11. } // namespace seamless
  12. #endif // RANK_H_

Rank.cc 实现


  1. #include <cstdlib>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <string>
  5. #include "IAPIProviderInterface.h"
  6. #include "IParameterInterface.h"
  7. #include "VariantField.h"
  8. #include "Rank.h"
  9. using namespace seamless;
  10. using namespace std;
  11. namespace seamless {
  12. void Rank::processQuery(IAPIProviderInterface* iAPIProvider) {
  13. IParameterInterface* iParameter = iAPIProvider->getParameterInterface();
  14. if (!iParameter) {
  15. cerr << "iParameter is NULL" << endl;
  16. return;
  17. }
  18. int32_t isRetailWholesale = 0;
  19. int32_t isUseAlipay = 0;
  20. VariantField* value = new VariantField;
  21. iParameter->getParameter("retail_wholesale", value);
  22. isRetailWholesale = (strcmp(value->strVal, "0")) ? 1 : 0;
  23. iParameter->getParameter("is_use_alipay", value);
  24. isUseAlipay = (strcmp(value->strVal, "0")) ? 1 : 0;
  25. cout << "isRetailWholesale:\t" << isRetailWholesale << endl;
  26. cout << "isUseAlipay:\t" << isUseAlipay << endl;
  27. delete value;
  28. delete iParameter;
  29. }
  30. } // namespace seamless
  • 从上面的例子中可以看出,引擎会传入一个IAPIProviderInterface对象,这个对象调用getParameterInterface()方法来得到Query中的Segment。
  • 因此,我们需要Mock的对象也比较清楚了,就是要模拟引擎将Query的Segment传给这个模块。其实就是让=模拟iParameter->getParameter方法:我想让它返回什么样的值就返回什么样的值.

下面我们开始Mock了:
MockIParameterInterface.h 模拟模拟IParameterInterface类


  1. #ifndef MOCKIPARAMETERINTERFACE_H_
  2. #define MOCKIPARAMETERINTERFACE_H_
  3. #include <boost/cstdint.hpp>
  4. #include <gmock/gmock.h>
  5. #include "IParameterInterface.h"
  6. #include "VariantField.h"
  7. namespace seamless {
  8. class MockIParameterInterface: public IParameterInterface {
  9. public:
  10. MOCK_METHOD2(getParameter, int32_t(const char* name, VariantField*& value));
  11. };
  12. } // namespace seamless
  13. #endif // MOCKIPARAMETERINTERFACE_H_

MockIAPIProviderInterface.h 模拟IAPIProviderInterface类


  1. #ifndef MOCKIAPIPROVIDERINTERFACE_H_
  2. #define MOCKIAPIPROVIDERINTERFACE_H_
  3. #include <gmock/gmock.h>
  4. #include "IAPIProviderInterface.h"
  5. #include "IParameterInterface.h"
  6. namespace seamless {
  7. class MockIAPIProviderInterface: public IAPIProviderInterface{
  8. public:
  9. MOCK_METHOD0(getParameterInterface, IParameterInterface*());
  10. };
  11. } // namespace seamless
  12. #endif // MOCKIAPIPROVIDERINTERFACE_H_

tester.cc

(3/5)上一页 下一页| 剩余全文

分享到:
  网友评论(0)
 
回到顶部