Google Mock: why is a partial ordering of expectations harder to satisfy than a total ordering?

After some more progress on the GoogleMock learning curve, I'll try to answer my own question in a way that is general enough to be helpful.

Let's consider the following example of totally ordered expectations:

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

Now, let's slice the ordering in two.

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

The intention is to allow expectations from the two sequences to "merge", i.e. to have expectation #1 as precondition for #2 and #3 for #4 but not more than that.

However, the following sequence of calls will satisfy the totally ordered expectations but not the "partially ordered" ones:

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

Reason: it is obvious why the totally ordered expectations are satisfied: the example just satisfies them in the order they are written. Being InSequence, they retire as soon as they are satisfied.

However, the "partially ordered" scenario doesn't work because call #1 will satisfy expectation #3, then call #2 will match against expectation #2, which can't be met because it has expectation #1 as precondition. Even though technically, expectations #1 and #3 are identical, they are satisfied in reverse order of writing, since they don't belong to the same ordering, hence the failure.

I have the feeling that this phenomenon is not well enough documented by Google Mock. I'm still looking for a better formalization. I suspect that there's something wrong with the "partial order" concept as used here.


Looking at your question and your answer, I think your case is a typical example of DAG (directed acyclic graph) which can be solved by InSequence clause to EXPECT_CALL (not the InSeqeunce class from ::testing:: namespace). See gmock Cookbook explanation here. Example test provided in your answer can be solved this way:

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

The above test code will make sure methodA is called before methodX and methodY. Also, it doesn't care in which order are methodX and methodY called.