How can I tell GoogleMock to stop checking an expectation after the test finished?
Asked Answered
R

1

14

I have two unit tests that share some state (unfortunately I can't change this since the point is to test the handling of this very state).

TEST(MySuite, test1)
{
    shared_ptr<MockObject> first(make_shared<MockObject>());
    SubscribeToFooCallsGlobal(first);
    EXPECT_CALL(*first, Foo(_));//.RetiresOnSaturation();
    TriggerFooCalls(); // will call Foo in all subscribed
}

TEST(MySuite, test2)
{
    shared_ptr<MockObject> second(make_shared<MockObject>());
    SubscribeToFooCallsGlobal(second);
    EXPECT_CALL(*second, Foo(_)).Times(1);
    TriggerFooCalls(); // will call Foo in all subscribed
}

If I run the tests separately, both are successful. If I run them in the order test1, test2, I will get the following error in test2:

mytest.cpp(42): error: Mock function called more times than expected - returning directly.
    Function call: Foo(0068F65C)
         Expected: to be called once
           Actual: called twice - over-saturated and active

The expectation that fails is the one in test1. The call does take place, but I would like to tell GoogleMock to not care after test1 is complete (in fact, I only want to check expectations in a test while the test is running).

I was under the impression that RetiresOnSaturation would do this, but with it I get:

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

mytest.cpp(42): EXPECT_CALL(first, Foo(_))...
         Expected: the expectation is active
           Actual: it is retired
         Expected: to be called once
           Actual: called once - saturated and retired

Which I have to admit, confuses me. What does it mean? How can I solve this?

Rudbeckia answered 14/10, 2015 at 12:56 Comment(9)
` SubscribeToFooCallsGlobal(first);` - you probably must unsubscribe it at the end of each TC.Cornelius
@Cornelius Sure, but that's a workaround. Why does GoogleMock still check the call after the test ran?Chatwin
Because globals are globals. And as such (those globals) are pain in the a*s - and nobody and nothing (including gtest) can deal properly with globalsCornelius
@Cornelius my point is: why doesn't GoogleMock clear the expectations after a test case ran? How can I make it clear them? To me it doesn't make sense to keep them in place after a test case finished running.Chatwin
Your mocks are still there (kept by your globals as std::shared_ptr) - so , how, according to you, gmock shall recognize they shall not participate in next test? My point is that they are subscribed - so they are called - but they expected to be called only onceCornelius
I mean in first test you have one Mock subscribed. In 2nd test you have 2 mocks subscribedCornelius
Use RAII/ScopeGuard to subscribed/unsubscibe your mocksCornelius
" it doesn't make sense to keep them in place" - my point is that this is you, you are keeping them in place - not gtest/gmockCornelius
@Cornelius I'm not debating why it is happening (I'm aware) but rather why gmock works like this and asking if there is a way to make tests run independently. If you are saying that the only way to do that is by destructing the mock objects, then kindly add that as an answer with the relevant documentation parts (which I failed to find) and I'll accept it as a solution.Chatwin
C
16

You can read in documentation of Mock almost literally described your case:

Forcing a Verification

When it's being destoyed, your friendly mock object will automatically verify that all expectations on it have been satisfied, and will generate Google Test failures if not. This is convenient as it leaves you with one less thing to worry about. That is, unless you are not sure if your mock object will be destoyed.

How could it be that your mock object won't eventually be destroyed? Well, it might be created on the heap and owned by the code you are testing. Suppose there's a bug in that code and it doesn't delete the mock object properly - you could end up with a passing test when there's actually a bug.

So you shall not expect, that at the end of the test case, in some magic way expectations will be "deactivated". As cited above - the mock destructor is the point of verification.

In your case - you mocks are not local variable - they are created in dynamic memory (heap in cited doc) and kept in your tested code via SubscribeToFooCallsGlobal(), So for sure mock created in one test is still alive in next test.

The easy, and proper solution is to unsubscribe at the end of each TC - I do not know if you have any UnsubscribeToFooCallsGlobal() - if not - create such function. To be sure that it will be always called - use ScopeGuard pattern.

There is one function to manually enforce verification Mock::VerifyAndClearExpectations(&mock_object) - but use it only if you need this verification not in the last line of your testcase, because that should be point of destruction.

edit: Fixed the googlemock link.

Cornelius answered 19/10, 2015 at 18:57 Comment(1)
You can also create Test Fixture class, and put this extra code to its TearDown method. This method is called after every test. You can also add SetUp method, which is called before every test.Flyman

© 2022 - 2024 — McMap. All rights reserved.