注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Google Mock进阶篇 [5] (Google Mock Cookbook译文)  

2012-04-29 14:53:34|  分类: C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Setting Expectations

Ignoring Uninteresting Calls

    如果你对一个Mock函数如何被调用不感兴趣,你可以不对它指定任何事。如果你这样做了,当这个函数被调用时,Google Mock会使用它的默认行为使测试可以得以进行下去。如果你不太喜欢这个默认的行为,你可以用DefaultValue<T>::Set()( 在这个文档的后面会讲到 )或是ON_CALL去覆盖默认行为。

    请注意一旦你对某个Mock函数表现出了兴趣( 通过EXPECT_CALL() ),所在对它的调用都需要匹配某个期望。如果这个函数被调用了,但参数没有匹配任何一个EXPECT_CALL语句,它将会产生一个错误。

Disallowing Unexpected Calls

    如果一个Mock函数根本不应该被调用,可以明确地指出:

using ::testing::_;

...

EXPECT_CALL(foo, Bar(_))

  .Times(0);

    如果对一个函数的某些调用是允许的,其它的调用则不行,则可以列出所有期望的调用:

using ::testing::AnyNumber;

using ::testing::Gt;

...

EXPECT_CALL(foo, Bar(5));

EXPECT_CALL(foo, Bar(Gt(10)))

  .Times(AnyNumber());

    如果一个调用不匹配任一EXPECT_CALL(),刚它会产生一个错误。

Expecting Ordered Calls

    尽管在Google Mock尝试匹配一个设置了期望的函数时,会优先匹配先定义的EXPECT_CALL语句,但默认的调用并不是必须以EXPECT_CALL()所写的顺序进行匹配。比如,如果参数匹配了第三个EXPECT_CALL,但没有匹配前两个EXPECT_CALL,那么就会使用第三个期望。

    如果你更好所有调用都以期望的顺序进行,将EXPECT_CALL()语句放到一个InSequence对象的生命周期中:

using ::testing::_;

using ::testing::InSequence;

 

{

   InSequence s;

  

   EXPECT_CALL(foo, DoThis(5));

   EXPECT_CALL(bar, DoThat(_))

      .Times(2);

   EXPECT_CALL(foo, DoThis(6));

}

    在这个例子中,我们期望调用以顺序如下:先调用foo.DoThis(5),然后两次参数为任意的bar.DoThat()调用,最后调用一次foo.DoThis()。如果调用的顺序与上面不符,则Google Mock会报告一个错误。

Expecting Partially Ordered Calls

    有时要求所有的调用都以一个预定义的顺序会导致测试脆弱。比如,也许我们会关心ABC之前调用,但不关心BC的调用顺序先后。在这种情况下,测试应当反应我们真正的意图,而不是写一个约束过强的语句。

    Google Mock在调用上设置一个顺序的任意DAG( directed acyclic graph 有向无环图 )。表达有DAG的一种方式是用EXPECT_CALLAfter子句。

    另一种方法是通过InSequence()子句( 不是InSequence ),这是我们从jMock 2中借鉴而来的。它比之After()稍失灵活,但当你有一长串顺序调用之时会更方便,因为它不要求你对长串中的期望都起一个不同的名字,下面是它如何工作的:

    如果我们视EXPECT_CALL()语句为图中的结点,添加一条从结点A到结点B的边,意思是A必须先于B出现,我们可以得到一个DAG。如果DAG被分解成了单独的顺序,我们只需要知道每个EXPECT_CALL在顺序中的位置,我们就可以重构出原来的DAG

    因此要为指定在期望之上的部分有序我们需要做两件事:第一定义一些Sequence对象,然后指明SequenceDAG中的部分。在同一顺序(sequence)中的期望必须以定义的先后(order)出现。比如:

using ::testing::Sequence;

 

Sequence s1, s2;

 

EXPECT_CALL(foo, A())

  .InSequence(s1, s2);

EXPECT_CALL(bar, B())

  .InSequence(s1);

EXPECT_CALL(bar, C())

  .InSequence(s2);

EXPECT_CALL(foo, D())

  .InSequence(s2);

    以上代码所指定的顺序为( 其中s1A->Bs2A->C->D )

       +---> B

       |

  A ---|

       |

       +---> C ---> D

    这意味着A必须先于BC出现,并且C必须在D之前出现,并除此之外没有其它的顺序要求。

Controlling When an Expectation Retires

    当一个Mock函数被调用时,Google Mock只考虑那些仍然有效的期望。一个期望在创建之时是有效的,当在它之上发生一次调用后,它就变为失效的了。比如,在:

using ::testing::_;

using ::testing::Sequence;

 

Sequence s1, s2;

 

EXPECT_CALL(log, Log(WARNING, _, "File too large."))     // #1

  .Times(AnyNumber())

  .InSequence(s1, s2);

EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))  // #2

  .InSequence(s1);

EXPECT_CALL(log, Log(WARNING, _, "User not found."))     // #3

  .InSequence(s2);

    只要#2#3任一匹配,#1就会失效。如果一个警告”File too large”在此之后调用,它将会产生一个错误。

    注意一个期望在它饱和后不会自动失效。例如:

using ::testing::_;

...

EXPECT_CALL(log, Log(WARNING, _, _));                  // #1

EXPECT_CALL(log, Log(WARNING, _, "File too large."));  // #2

    上面的代码意思是有仅只能有一个”File too large”的警告。如果第二个警告仍然是”File too large”#2仍然会匹配并且产生一个超出上界的错误。

    如果这不是你想要的,你可以让一个期望在饱和之后就失效:

using ::testing::_;

...

EXPECT_CALL(log, Log(WARNING, _, _));                 // #1

EXPECT_CALL(log, Log(WARNING, _, "File too large."))  // #2

  .RetiresOnSaturation();

  评论这张
 
阅读(1877)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017