谷歌模拟:为什么部分订购的期望难以满足总订购?

时间:2014-10-02 12:02:00

标签: c++ googlemock expectations

我主要使用GoogleMock的有序期望,因此所有EXPECT_CALL都写在testing::InSequence对象的范围内。

现在我想放松排序,所以我将期望分成2个序列。你会说测试应该通过,但是没有 - 它失败了,抱怨未满足的前提条件。我该怎么推理呢?

编辑:我的代码缩减版本:

//InSequence s;                                     // uncomment this and it works
for (int i = 1; i <= 2; ++i)
{
    {
        //InSequence s;                             // uncomment this and it doesn't work

        EXPECT_CALL(mock1, produceMessage(_))
            .WillOnce(DoAll(SetArgReferee<0>(val1), Return(false)))
            .WillOnce(DoAll(SetArgReferee<0>(val2), Return(false)))
            .WillOnce(DoAll(SetArgReferee<0>(val2), Return(false)));

        EXPECT_CALL(mock2, handleEvent(A<MyType>()));
        EXPECT_CALL(mock2, handleMessage(NotNull()));
    }
}

因此,如果InSequence嵌套在for循环内,我应该有一个部分顺序,这是一个宽松的要求,与InSequence在外面的情况相比。

我得到的错误:

Mock function called more times than expected - returning default value.
    Function call: handleMessage(0xd7e708)
          Returns: false
         Expected: to be called once
           Actual: called twice - over-saturated and active

然后,在测试结束时:

Actual function call count doesn't match EXPECT_CALL(mock2, handleMessage(NotNull()))...
         Expected: to be called once
           Actual: never called - unsatisfied and active

2 个答案:

答案 0 :(得分:5)

在GoogleMock学习曲线取得更多进展后,我会尝试以一般性的方式回答我自己的问题。

让我们考虑以下完全有序期望的例子:

{
    InSequence s;

    EXPECT_CALL(mock1, methodA(_));     // expectation #1
    EXPECT_CALL(mock2, methodX(_));     // expectation #2

    EXPECT_CALL(mock1, methodA(_));     // expectation #3
    EXPECT_CALL(mock2, methodY(_));     // expectation #4
}

现在,让我们将排序分成两部分。

{
    InSequence s;

    EXPECT_CALL(mock1, methodA(_));     // expectation #1
    EXPECT_CALL(mock2, methodX(_));     // expectation #2
}

{
    InSequence s;

    EXPECT_CALL(mock1, methodA(_));     // expectation #3
    EXPECT_CALL(mock2, methodY(_));     // expectation #4
}

目的是允许来自两个序列的期望&#34;合并&#34;,即期望#1作为#2的前提条件,#3作为#4的前提条件但不超过#4。

然而,以下呼叫顺序将满足完全有序的期望,但不满足&#34;部分有序&#34;的:

mock1.methodA();   // call #1
mock2.methodX();   // call #2
mock1.methodA();   // call #3
mock2.methodY();   // call #4

原因:很明显为什么满足完全有序的期望:这个例子只是按照它们的编写顺序来满足它们。成为InSequence,他们会在满意后立即退休。

然而,&#34;部分订购&#34;方案不起作用,因为#1呼叫将满足期望#3,然后呼叫#2将匹配期望#2,因为它具有期望#1作为前提条件,所以不能满足期望#2。尽管在技术上,期望#1和#3是相同的,但它们以相反的顺序排列,因为它们不属于相同的顺序,因此失败。

我觉得Google Mock记录的这种现象还不够好。我还在寻找更好的形式化。我怀疑&#34;部分订单&#34;是否有问题。这里使用的概念。

答案 1 :(得分:0)

看看您的问题和答案,我认为您的案例是DAG(有向无环图)的典型示例,可以通过EXPS_CALL的InSequence子句(而非:: testing ::名称空间的InSeqeunce类)解决。请参阅gmock Cookbook说明here。 答案中提供的示例测试可以通过以下方式解决:

Sequence s1, s2;
EXPECT_CALL(mock1, methodA(_)).InSequence(s1, s2);
EXPECT_CALL(mock2, methodX(_)).InSequence(s1);
EXPECT_CALL(mock2, methodY(_)).InSequence(s2);

上面的测试代码将确保在methodX和methodY之前调用methodA。另外,它并不关心methodX和methodY的调用顺序。