C++ 谷歌模拟:为什么期望的部分排序比完全排序更难满足?

C++ 谷歌模拟:为什么期望的部分排序比完全排序更难满足?,c++,googlemock,expectations,C++,Googlemock,Expectations,我主要使用GoogleMock的有序期望,因此所有EXPECT\u调用s都是在testing::insessue对象的范围内编写的 现在我想放松排序,所以我将期望分为两个序列。你可能会说测试应该通过,但不——它失败了,抱怨没有满足先决条件。我该怎么解释呢 编辑:我的代码的简化版本: //InSequence s; // uncomment this and it works for (int i = 1; i <= 2

我主要使用GoogleMock的有序期望,因此所有
EXPECT\u调用
s都是在
testing::insessue
对象的范围内编写的

现在我想放松排序,所以我将期望分为两个序列。你可能会说测试应该通过,但不——它失败了,抱怨没有满足先决条件。我该怎么解释呢

编辑:我的代码的简化版本:

//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()));
    }
}
然后,在测试结束时:

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

在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和4的先决条件,但不超过此

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

原因:很明显,为什么完全有序的期望会得到满足:示例只是按照它们编写的顺序来满足它们。作为一个不连续的人,他们一满意就退休

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


我觉得Google Mock对这种现象的记录还不够充分。我仍然在寻找更好的形式化。我怀疑这里使用的“偏序”概念有问题。

看看你的问题和答案,我认为你的案例是DAG(有向无环图)的一个典型例子,它可以通过INSESQUENCE子句来解决,以期待调用(而不是来自::testing::namespace的INSEQENCE类)。请参阅gmock食谱说明。 答案中提供的示例测试可通过以下方式解决:

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的调用顺序也不重要。

你能写一些示例代码吗?只是添加了代码。附加说明:在第三个期望中添加
.RetiresOnSaturation()
修复了偏序情况。但不是我的真实案例,更复杂。produceMessage看起来怎么样?你找到这个问题的解决方案了吗?没有。不是一般的解决方案。我相信一个通用的解决方案需要某种形式的回溯,但我没有更多的考虑。谢谢。我能够解决这个问题的变体,因为我可以通过其中一个参数的值来区分任一块中的methodA。然后让methodA在第一个块中匹配该值,在第二个块中匹配除该值以外的所有值。显然,这不会适用于任何地方,它正好适合我的问题。
mock1.methodA();   // call #1
mock2.methodX();   // call #2
mock1.methodA();   // call #3
mock2.methodY();   // call #4
Sequence s1, s2;
EXPECT_CALL(mock1, methodA(_)).InSequence(s1, s2);
EXPECT_CALL(mock2, methodX(_)).InSequence(s1);
EXPECT_CALL(mock2, methodY(_)).InSequence(s2);