6

我主要使用 GoogleMock 的有序期望,所以所有EXPECT_CALLs 都写在对象的范围内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
4

2 回答 2

9

在 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
}

目的是允许来自两个序列的期望“合并”,即期望#1 作为#2 的先决条件,#3 作为#4 的先决条件,但不超过此。

但是,以下调用序列将满足完全有序的期望,但不能满足“部分有序”的期望:

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

原因:完全有序的期望得到满足的原因很明显:示例只是按照它们编写的顺序满足它们。是InSequence,他们一满意就退休。

但是,“部分排序”的场景不起作用,因为调用 #1 将满足期望 #3,然后调用 #2 将与期望 #2 匹配,因为它以期望 #1 作为前提条件而无法满足。尽管从技术上讲,期望 #1 和 #3 是相同的,但它们以相反的写作顺序得到满足,因为它们不属于相同的顺序,因此失败。

我感觉 Google Mock 对这种现象的记录不够好。我仍在寻找更好的形式化。我怀疑这里使用的“部分订单”概念有问题。

于 2014-10-09T09:53:01.603 回答
2

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

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 的调用顺序。

于 2019-12-13T12:22:16.333 回答