zoukankan      html  css  js  c++  java
  • gmock使用、原理及源码分析

    1      初识gmock

    1.1      什么是Mock

    便捷的模拟对象的方法。

    1.2      Google Mock概述

    google mock是用来配合google test对C++项目做单元测试的。它依赖于googletest

    Google Mock(简称gmock)是Google在2008年推出的一套针对C++的Mock框架,它灵感取自于jMockEasyMockharcreat。它提供了以下这些特性:

    • 轻松地创建mock类
    • 支持丰富的匹配器(Matcher)和行为(Action)
    • 支持有序、无序、部分有序的期望行为的定义
    • 多平台的支持

    1.3      获取、编译google mock

    见gtest,gtest项目里就包含gmock

    1.4      最简单的例子

    class MockFoo: public FooInterface {
    public:
            MOCK_METHOD0(getArbitraryString, std::string());
    };
    
    using ::testing::Return;
    
    int main(int argc, char** argv) {
            ::testing::InitGoogleMock(&argc, argv);
    
            string value = "Hello World!";
            MockFoo mockFoo;
            EXPECT_CALL(mockFoo, getArbitraryString()).Times(1).
                    WillOnce(Return(value));
            string returnValue = mockFoo.getArbitraryString();
            cout << "Returned Value: " << returnValue << endl;
    
            return EXIT_SUCCESS;
    }

    2      典型的流程

    通过上述的例子,已经可以看出使用Mock类的一般流程如下:

    • 引入你要用到的Google Mock名称. 除宏或其它特别提到的之外所有Google Mock名称都位于*testing*命名空间之下.
    • 建立模拟对象(Mock Objects).
    • 可选的,设置模拟对象的默认动作.
    • 在模拟对象上设置你的预期(它们怎样被调用,应该怎样回应?).

    2.1      自定义方法/成员函数的期望行为

    在单元测试/主程序中使用这个Mock类中的方法时最关键的就是对期望行为的定义。

    对方法期望行为的定义的语法格式如下:

    EXPECT_CALL(mock_object, method(matcher1, matcher2, ...))
        .With(multi_argument_matcher)
        .Times(cardinality)
        .InSequence(sequences)
        .After(expectations)
        .WillOnce(action)
        .WillRepeatedly(action)
        .RetiresOnSaturation();

    解释一下这些参数(虽然很多我也没弄明白):

    • 第1行的mock_object就是你的Mock类的对象
    • 第1行的method(matcher1, matcher2, …)中的method就是你Mock类中的某个方法名,比如上述的getArbitraryString;而matcher(匹配器)的意思是定义方法参数的类型,我们待会详细介绍。
    • 第3行的Times(cardinality)的意思是之前定义的method运行几次。至于cardinality的定义,我也会在后面详细介绍。
    • 第4行的InSequence(sequences)的意思是定义这个方法被执行顺序(优先级),我会再后面举例说明。
    • 第6行WillOnce(action)是定义一次调用时所产生的行为,比如定义该方法返回怎么样的值等等。
    • 第7行WillRepeatedly(action)的意思是缺省/重复行为。

    先举个例子来说明一下,后面有针对更为详细的说明:

    EXPECT_CALL(mockTurtle, getX()).Times(testing::AtLeast(5)).
                    WillOnce(testing::Return(100)).WillOnce(testing::Return(150)).
                    WillRepeatedly(testing::Return(200))

    这个期望行为的定义的意思是:

    • 调用mockTurtle的getX()方法
    • 这个方法会至少调用5次
    • 第一次被调用时返回100
    • 第2次被调用时返回150
    • 从第3次被调用开始每次都返回200

    2.2      Matcher(匹配器)

    Matcher用于定义Mock类中的方法的形参的值(当然,如果你的方法不需要形参时,可以保持match为空。),就是判断在调用这个函数时,入参的值是否符合预先设置的条件,就是一个预设的EXPECT_TRUE。

    它有以下几种类型:

    一般比较、浮点数的比较、字符串匹配、容器的匹配、成员匹配器、匹配函数或函数对象的返回值、指针匹配器、复合匹配器

    具体参考原文吧https://www.cnblogs.com/welkinwalker/archive/2011/11/29/2267225.html

    2.3      基数(Cardinalities)

    基数用于Times()中来指定模拟函数将被调用多少次|

    2.4      行为(Actions)

    Actions(行为)用于指定Mock类的方法所期望模拟的行为:比如返回什么样的值、对引用、指针赋上怎么样个值,等等。 值的返回

    Return()

    让Mock方法返回一个void结果

    Return(value)

    返回值value

    ReturnNull()

    返回一个NULL指针

    ReturnRef(variable)

    返回variable的引用.

    ReturnPointee(ptr)

    返回一个指向ptr的指针

    另一面的作用(Side Effects

    Assign(&variable, value)

    将value分配给variable

    使用函数或者函数对象(Functor)作为行为

    Invoke(f)

    使用模拟函数的参数调用f, 这里的f可以是全局/静态函数或函数对象.

    Invoke(object_pointer, &class::method)

    使用模拟函数的参数调用object_pointer对象的mothod方法.

    复合动作

    DoAll(a1, a2, …, an)

    每次发动时执行a1到an的所有动作.

    IgnoreResult(a)

    执行动作a并忽略它的返回值. a不能返回void.

    复合行为举例:

        EXPECT_CALL(mockIParameter, getParamter(testing::_, testing::_)).Times(1).
            WillOnce(testing::DoAll(testing::Assign(&a, b), testing::Return(1)));

    2.5      序列(Sequences)

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

    3      Google Mock Cookbook

    3.1      Mock protected、private方法

    Google Mock也可以模拟protected和private方法,比较神奇啊(其实从这点上也可以看出,Mock类不是简单地继承原本的接口,然后自己把它提供的方法实现;Mock类其实就等于原本的接口)。

    对protected和private方法的Mock和public基本类似,只不过在Mock类中需要将这些方法设置成public。

    3.2      Mock 模版类(Template Class)

    Google Mock可以Mock模版类,只要在宏MOCK*的后面加上T。

    4      Gmock原理及源码分析

    4.1      基本原理

    EXPECT_CALL.WillOnce的核心工作: untyped_actions_.push_back(new Action<F>(action)); 也就是说它将返回值塞进了一个vector容器中。

    MOCK_METHOD0的核心工作:this->UntypedInvokeWith(&args))->GetValueAndDelete();也就是说它从之前说的那个vector中取出返回的结果被删除。

    参见:单元测试Mock之c++ gmock实现原理 https://www.jianshu.com/p/06f0a7d85877

    4.2      源码分析

    参见:Google Mock(Gmock)简单使用和源码分析——源码分析 https://blog.csdn.net/breaksoftware/article/details/51438033

    5      参考文档

    转一篇小亮同学的google mock分享https://www.cnblogs.com/welkinwalker/archive/2011/11/29/2267225.html

    单元测试Mock之c++ gmock实现原理 https://www.jianshu.com/p/06f0a7d85877

    Google Mock(Gmock)简单使用和源码分析——源码分析 https://blog.csdn.net/breaksoftware/article/details/51438033

    官网,但我今天打不开官网了。

  • 相关阅读:
    Tomcat给我的java.lang.OutOfMemoryError: PermGen
    解决:dubbo找不到dubbo.xsd报错
    html li css选中状态切换
    JavaScript jQuery 中定义数组与操作及jquery数组操作 http://www.jb51.net/article/76601.htm
    Hibernate中多对多的annotation的写法(中间表可以有多个字段)
    @OneToMany、@ManyToOne以及@ManyToMany讲解
    mysql中char,varchar与text类型的区别和选用
    MYSQL数据库设计规范与原则
    使用fastJSON解析HashMap中的数据
    python测试开发django-29.发送html格式邮件
  • 原文地址:https://www.cnblogs.com/aoyihuashao/p/9362003.html
Copyright © 2011-2022 走看看