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定位,从某个侧面来说,提高的编码效率。现在,不论用什么语言写程序,在熟悉了语言本身之后,第一件事就是去熟悉这门语言相关的单元测试框架。

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

 

参考资料

posted @ 2012-01-20 08:51  bourneli  阅读(14253)  评论(0编辑  收藏  举报