zoukankan      html  css  js  c++  java
  • something about Google Mock / gmock使用小结

    下载gmock:http://code.google.com/p/googlemock/downloads/list

    安装:将下载的压缩包解压出来,到解压目录下执行:

    ./configure

    然后执行:

    make

    注意,这个make不会编译Google Mock自己的测试用例。要编译它们,需要到解压目录下的“make”子目录下,执行:

    make gmock_test

    文章来源:http://www.codelast.com/

    然后就会看到该目录下生成了一个可执行文件 gmock_test ,执行这个可执行文件,就可以看到Google Mock测试用例的执行结果(应该是成功的,如果有失败,则应修改Makefile使之成功):

    Running main() from gmock_main.cc

    [==========] Running 13 tests from 3 test cases.

    [----------] Global test environment set-up.

    [----------] 6 tests from InitGoogleMockTest

    [ RUN      ] InitGoogleMockTest.ParsesInvalidCommandLine

    [       OK ] InitGoogleMockTest.ParsesInvalidCommandLine (0 ms)

    [ RUN      ] InitGoogleMockTest.ParsesEmptyCommandLine

    [       OK ] InitGoogleMockTest.ParsesEmptyCommandLine (0 ms)

    [ RUN      ] InitGoogleMockTest.ParsesSingleFlag

    [       OK ] InitGoogleMockTest.ParsesSingleFlag (0 ms)

    [ RUN      ] InitGoogleMockTest.ParsesUnrecognizedFlag

    [       OK ] InitGoogleMockTest.ParsesUnrecognizedFlag (0 ms)

    [ RUN      ] InitGoogleMockTest.ParsesGoogleMockFlagAndUnrecognizedFlag

    [       OK ] InitGoogleMockTest.ParsesGoogleMockFlagAndUnrecognizedFlag (0 ms)

    [ RUN      ] InitGoogleMockTest.CallsInitGoogleTest

    [       OK ] InitGoogleMockTest.CallsInitGoogleTest (0 ms)

    [----------] 6 tests from InitGoogleMockTest (1 ms total)

    [----------] 6 tests from WideInitGoogleMockTest

    [ RUN      ] WideInitGoogleMockTest.ParsesInvalidCommandLine

    [       OK ] WideInitGoogleMockTest.ParsesInvalidCommandLine (0 ms)

    [ RUN      ] WideInitGoogleMockTest.ParsesEmptyCommandLine

    [       OK ] WideInitGoogleMockTest.ParsesEmptyCommandLine (0 ms)

    [ RUN      ] WideInitGoogleMockTest.ParsesSingleFlag

    [       OK ] WideInitGoogleMockTest.ParsesSingleFlag (0 ms)

    [ RUN      ] WideInitGoogleMockTest.ParsesUnrecognizedFlag

    [       OK ] WideInitGoogleMockTest.ParsesUnrecognizedFlag (0 ms)

    [ RUN      ] WideInitGoogleMockTest.ParsesGoogleMockFlagAndUnrecognizedFlag

    [       OK ] WideInitGoogleMockTest.ParsesGoogleMockFlagAndUnrecognizedFlag (0 ms)

    [ RUN      ] WideInitGoogleMockTest.CallsInitGoogleTest

    [       OK ] WideInitGoogleMockTest.CallsInitGoogleTest (0 ms)

    [----------] 6 tests from WideInitGoogleMockTest (0 ms total)

    [----------] 1 test from FlagTest

    [ RUN      ] FlagTest.IsAccessibleInCode

    [       OK ] FlagTest.IsAccessibleInCode (0 ms)

    [----------] 1 test from FlagTest (0 ms total)

    [----------] Global test environment tear-down

    [==========] 13 tests from 3 test cases ran. (1 ms total)

    [  PASSED  ] 13 tests.

    文章来源:http://www.codelast.com/

    其他记录:

    (1)Google Mock对象在析构的时候会检查mock函数的执行结果是否与预期相符,如果mock对象一直存在,最终的检查就不会发生。因此,如果你在堆(heap)中创建mock对象的话,最好使用内存泄漏检查工具来确定你的test是否做好了mock对象销毁工作。

    (2)Google Mock要求在调用mock函数之前设置好预期的结果,否则其行为就是“未定义”的。

    (3)使用EXPECT_CALL() 宏来设置一个mock函数调用的预期结果。其语法为:

    EXPECT_CALL(mock_object, method(matchers))

    .Times(cardinality)

    .WillOnce(action)

    .WillRepeatedly(action);

    第一个参数是mock对象,第二个参数是mock函数名及其参数。二者中间是以逗号(而不是点号)分隔的,至于为什么是这样,回答只有一个:技术原因。

    宏后面还可以紧跟若干语句,以提供对mock函数调用的预期结果的更多信息。这种风格的语法被一些人称作是“特定领域语言”(Domain-Specific Language,DSL)。

    (4)Google Mock中有一些可能初次见到时感觉比较陌生的概念,例如 matcher,cardinality,etc.  这些概念在gmock的手册中都有详细说明,网上也可以找到一些中文文档,为了能真正用起来gmock,一定要看清了这些概念的含义。

    (5)一个返回值为 bool 类型的mock函数默认是返回 false 的!所以,如果你没有设置函数的默认返回值,你的test函数被调用了之后很可能只执行了一部分(例如,你的test函数调用了一个mock函数,而该函数在返回 false 时,将不再继续执行其后的代码),这样你的test将不能覆盖某函数的全部代码,而这并不是你乐见的,切记。

    (6)在mock对象析构时,对“期望”的检验才会被执行,所以,如果你的mock对象一直没有析构(例如,你在堆中创建了一个mock对象,却忘了删除它 。有人说可以用内存检查工具来防止这一点,但是要知道没有工具是可以保证100%可靠的),则检验一直不会被执行。如果你担心这种情况,就可以主动进行检验:

    Mock::VerifyAndClearExpectations(&mock_object):

    该方法返回一个bool值,以显示检验是否成功(true代表成功)。所以,你可以把它嵌套在EXPECT_TRUE()或者ASSERT_TRUE()里面来测试检验结果。

    文章来源:http://www.codelast.com/

    (7)gmock安装包解压目录下的“scripts”子目录下,有一个Python脚本fuse_gmock_files.py,这个脚本一般用不到,它是用来合并Google Mock的文件的。Google Mock包含N多文件,如果你要自己扩充它的功能,那么你就需要自行修改某些文件的源码,如果你把Google Mock拷贝到另一台计算机上,从头开始修改很多个文件的源码可能就很麻烦,所以脚本fuse_gmock_files.py就可以将Google Mock原来的N多文件合并为三个文件:gtest/gtest.h,gmock/gmock.h 和 gmock-gtest-all.cc。这样的话就方便多了。

    (8)Google Mock有三个(主要的)指导文档,其难度由低到高分别为:ForDummies,CheatSheet,CookBook。所以,如果你刚接触gmock,应该按这个顺序依次学习那三个文档。

    (9)对普通函数,使用宏 MOCK_METHODn 来定义一个模拟函数,其中n是你要模拟的函数的参数的个数,例如,你要模拟的函数没有参数,则应使用 MOCK_METHOD0。对const函数,你就要改用宏 MOCK_CONST_METHODn 来定义。

    (10)static/静态 函数如何mock?

    在Google Mock的官方“常见问题”的回答中(请点击这个链接,在文章中搜索“static”即可定位到),Google是这样说的:You can, but you need to make some changes(可以,但是你需要做一些修改).Google说,如果你需要mock一个静态函数,那说明你的程序模块过于“紧耦合”了(并且灵活性不够、重用性不够、可测试性不够),你最好是定义一个小接口,通过这个接口来调用那个函数,然后就容易mock了。

    这就是Google Mock给出的答案,至于你怎么想的,又会不会按它的建议去做,决定权就在你自己了。

    (11)使用 ON_CALL() 宏可以设定mocker函数的返回值,例如以下代码:

      

    ON_CALL(myMockObj, myFunc())

        .WillByDefault(Return(123));

    表示“命令”函数 myFunc() 的返回值为 123,其中 myMockObj 是mocker对象,函数 myFunc() 是在该mocker类中定义的模拟函数。可见,有了Goolge Mock这样的工具,我们就可以随意“控制”一个函数的行为,让它返回我们想要返回的值,从而可以使得单元测试可以按我们的意愿来进行——有时候,你必须要这么做,例如,你的一个函数 myInvoker() 调用了 myFunc() 函数,而myFunc() 函数的返回值是根据当前时间而变化的,因此其返回值不定,我们无法使其返回一个固定的值,从而我们在对 myInvoker() 做单元测试的时候,就“很难测”了,这个时候,我们就要命令 myFunc() 永远返回我们想要的值,从而可以使得对 myInvoker() 的单元测试可以顺利进行。

    多么妙的想法!这就是mock的巨大作用,尽管它只是一个后台的“模仿者”(mocker),但是它产生的作用,却是真真切切的。

    文章来源:http://www.codelast.com/

    (12)编译你自己的单元测试的时候遇到“undefined reference to `vtable for XXX”,“undefined reference to `typeinfo for XXX'”错误?

    出现这个错误,我可以提醒你的一点是:检查你的mocker类中,是否按照gmock文档的要求,把某些函数定义成纯虚函数了。比如我有一个tobe mocked的类:

    class CTobeMocked

    {

    public:

        CTobeMocked() {}

        virtual ~CTobeMocked() {}

    public:

        virtual double myFunc(const string &str) = 0;

    };

    这个类就是要被mock的类,注意里面的函数myFunc()是被定义成纯虚函数的,如果你漏了后面的“ = 0”,那么你编写了相应的mocker类之后,编译的时候就会出错。

    我的mocker类如下:

    class CMyMocker : public CTobeMocked

    {

    public:

        CMyMocker() {}

        virtual ~CMyMocker() {}

    public:

        MOCK_METHOD(myFunc, double(const string &str));

    };

  • 相关阅读:
    HihoCoder 1638 : 小Hi的天平 (2-sat+并查集)
    阿里云安全肖力:云上数据安全体系建设的六要素
    MaxCompute客户端(odpscmd)在windows命令行下查询中文乱码问题处理实践
    序列化方案选型对比
    亚洲唯一,阿里云SLB位列Gartner全球网络负载均衡市场前五
    阿里云OSS同城冗余存储技术解析
    OSS跨同城3AZ重磅发布,构造全面数据保护体系
    阿里云OSS同城冗余存储正式商业化,提供云上同城容灾能力
    云原生应用 Kubernetes 监控与弹性实践
    GIAC2019 演讲精选 | 面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码
  • 原文地址:https://www.cnblogs.com/iloveyoucc/p/2534338.html
Copyright © 2011-2022 走看看