GoogleMock: how to expect precisely one call with

2019-05-30 17:43发布

问题:

Maybe a finesse question, my problem is that if I write:

EXPECT_CALL(mock, handleMessage(_)).Times(0);                           // expectation #1
EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage))));    // expectation #2

... and method handleMessage is called once, but with a different argument (not aSpecificMessage), then the failure looks like:

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

Google Mock doesn't print the diagnostic on why the argument didn't match the predicate in expectation #2. This is presumably because expectation #1 is the first to fail (?).

If I omit expectation #1, then the failure is verbose, along the lines of:

Google Mock tried the following 1 expectation, but it didn't match:

../../test/Test.cpp:143: EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage))))...
  Expected arg #0: points to a value that <....>
           Actual: 0xfeaf18, which points to <.....>

I'm using a custom Matcher IsLike and I went through the trouble of generating very explicit mismatch reasons, I'd like them to be printed. I also would not want to give up expectation #1 because that goes in a "default" section and by default I want no calls on that mock throughout the rest of the tests.

回答1:

Looks like you should use the StrictMock template modifier. Let's use this simple class and mock:

struct Foo
{
    virtual void function(int) {
    }
};

struct MockFoo: public Foo
{
    MOCK_METHOD1(function, void(int x));
};

Let's start with a basic test that exercises that method:

TEST(MockTest, basic_one_expectation)
{
    MockFoo foo;
    EXPECT_CALL(foo, function(4));
    Foo& foo1(foo);
    foo1.function(3);
}

Output:

[ RUN      ] MockTest.basic_one_expectation
unknown file: Failure

Unexpected mock function call - returning directly.
    Function call: function(3)
Google Mock tried the following 1 expectation, but it didn't match:

mock-test.cpp:298: EXPECT_CALL(foo, function(4))...
  Expected arg #0: is equal to 4
           Actual: 3
         Expected: to be called once
           Actual: never called - unsatisfied and active
mock-test.cpp:298: Failure
Actual function call count doesn't match EXPECT_CALL(foo, function(4))...
         Expected: to be called once
           Actual: never called - unsatisfied and active
[  FAILED  ] MockTest.basic_one_expectation (1 ms)

That's one of the alternatives you've already considered, but you don't want it because you have other tests that don't have any particular expectations about whether the function is called, and you want those tests to fail if the function gets called anyway. As a reminder, let's see what happened when we try such a test:

TEST(MockTest, basic_no_expectation)
{
    MockFoo foo;
    Foo& foo1(foo);
    foo1.function(3);
}

Output:

[ RUN      ] MockTest.basic_no_expectation

GMOCK WARNING:
Uninteresting mock function call - returning directly.
    Function call: function(3)
Stack trace:
[       OK ] MockTest.basic_no_expectation (1 ms)

We get a warning, but the test still passes. That's no good for you. Let's see what effect StrictMock has:

TEST(MockTest, strict_no_expectation)
{
    ::testing::StrictMock<MockFoo> foo;
    Foo& foo1(foo);
    foo1.function(3);
}

Output:

[ RUN      ] MockTest.strict_no_expectation
unknown file: Failure
Uninteresting mock function call - returning directly.
    Function call: function(3)
[  FAILED  ] MockTest.strict_no_expectation (0 ms)

We didn't have to explicitly say that we don't want the function to be called, but when the function gets called anyway, the test correctly fails. Exactly what you wanted.

Finally, let's look at what happens with StrictMock in the case where there are explicit expectations for the function's argument:

TEST(MockTest, strict_one_expectation)
{
    ::testing::StrictMock<MockFoo> foo;
    EXPECT_CALL(foo, function(4));
    Foo& foo1(foo);
    foo1.function(3);
}

Output:

[ RUN      ] MockTest.strict_one_expectation
unknown file: Failure

Unexpected mock function call - returning directly.
    Function call: function(3)
Google Mock tried the following 1 expectation, but it didn't match:

mock-test.cpp:307: EXPECT_CALL(foo, function(4))...
  Expected arg #0: is equal to 4
           Actual: 3
         Expected: to be called once
           Actual: never called - unsatisfied and active
mock-test.cpp:307: Failure
Actual function call count doesn't match EXPECT_CALL(foo, function(4))...
         Expected: to be called once
           Actual: never called - unsatisfied and active
[  FAILED  ] MockTest.strict_one_expectation (0 ms)

The diagnostics show the reason the argument didn't match, just like the original basic_one_expectation test shown above.