• gmock学习03自定义输出参数


    本文目的

    使用gmock时,有时候需要向被mock的函数输入一些自定以参数,用来测试调用mock的方法的各种的执行情况。前几天在项目中遇到这个问题,并使用了该技巧,觉得很有用,所以总结出来,作为备忘。

    一个例子

    XXXClient是一个类,用于和远端服务器交互,内部实现涉及网络通讯。

    class XXXClient {
    public:
        void QueryXXX(const Request&, Response&);
    }; 

    内部有个函数QueryXXX,用于执行查询操作。查询的响应对象通过引用的方式传回给调用对象,避免不必要的对象拷贝。

    现在有个类,会调用XXXClient::QueryXXX方法,如下面所示:

    class XXXRunner {
    public:
        QueryResult DoSomething(XXXClient& oClient)
        {
            Request oReq;
            … // 设置oReq
    
            Response oRsp;
            oClient.QueryXXX(oReq, oRsp);
        
            // 这里以后的逻辑需要测试
             … // 根据oRsp的内容,做一些相关逻辑,并创建QueryResult对象
    
             return oResult;
        }
    };

    现在希望做的是在测试用例中设置各种输出(oRsp),测试调用QueryXXX之后的代码逻辑,更重要的是,不希望为了执行单元测试,专门搭建一个服务器与XXXClient交互,成本太高

    Gmock的解决方法

    gmock内部实现了一系列Action的宏,可以帮我们完成上面的需求。先看看代码,首先mock我们的XXXClient,

    class XXXClientMock : public XXXClient
    {
    public:
        MOCK_METHOD2(QueryXXX, QueryResult (Request&, Response&));
    };

    Mock的XXXClient后,我们就可以使用mock对象在单元测试中测试了。

    TEST(XXXRunnerTC, SetArgRefereeDemo)
    {
        XXXCLientMock oMock;
    
        // 设计一个期望的oRsp返回对象
        Response oRsp;
        oRsp.attr1 = “…”; 
        oRsp.attr2 = “any thing you like”;
    
        // 关联oRsp与mock对象的Query
        EXPECT_CALL(oMock,  QueryXXX(_, _)).
        WillOnce(SetArgReferee<1>(oRsp));
        // OK 设置完毕
    
        // 调用QueryXXX
        XXXRunner oRunner;
        QueryResult oRst = oRunner.DoSomething(oMock);
        …
    
        // 设置断言
        EXPECT_EQ(“abcdefg”, oRst.attr1);
        ……
    }

     

    Gmock的Action

    好了,现在解决了本文开始提出的问题,可以捎带做一点扩展阅读。上面用的一些API,在Gmock中称之为Action(行为),主要目的是方便快速的为mock类提供测试行为,用于测试。上面,填充oRsp对象就是用SetArgReferee<N>(value)行为实现的,通过名字,可以知道这个行为对象是用于设置参数,N是参数的索引,从0开始。类似的行为还有SetArgPointee<N>(value),设置指针参数, SetArrayArgument<N>(first, last),设置数组参数,数组范围[first,last)

    设置返回值,可以使用行为Return(Value)等一些列API,更详细的可以阅读最后的“参考资料中的gmock cheat sheet”。

    有时候,可能需要设置参数和返回值,也就是同时设置多个行为,那么可以使用DoAll函数帮我们实现,DoAll相当于一个action的集合,使用示例如下:

    …
    EXPECT_CALL(oMock,  QueryXXX(_, _)).
        WillOnce(DoAll(SetArgReferee<1>(oRsp), Return(someObj))));
    …

    还可以通过Invoke行为,将负责的测试行为添加进来。

    总结

    用了Gtest&Gmock框架一段时间了,发现使用之他们之后,的确可以提升代码质量,并且加快bug定位,从某个侧面来说,提高的编码效率。现在,不论用什么语言写程序,在熟悉了语言本身之后,第一件事就是去熟悉这门语言相关的单元测试框架。

    个人认为写单元测试不只是一种行为,更是一种信仰。

    参考资料

  • 相关阅读:
    3.2spring源码系列----循环依赖源码分析
    3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖
    Jetson AGX Xavier ROS 调用usb单目摄像头运行ORB_SLAM2
    Jetson AGX Xavier ROS下调用USB单目摄像头
    SpringCloud-OpenFeign组件的使用
    SpringCloud-服务间通信方式
    SpringCloud-服务注册中心
    SpringCloud入门
    K8s—集群搭建
    Redis—过期策略以及内存淘汰机制
  • 原文地址:https://www.cnblogs.com/bourneli/p/2327734.html
Copyright © 2020-2023  润新知