Re: How to write an expectation like: Whenever the constructor of a mocked class is called expect the call of the destructor too ?

4,221 views
Skip to first unread message

Martin Svensson

unread,
Sep 11, 2012, 2:24:25 AM9/11/12
to googl...@googlegroups.com
Doing stuff in constructors is a bit tricky, because no virtually overridden methods are available there, so StrictMock does not work.
Mentioned here in caveat #3: http://code.google.com/p/googlemock/wiki/CookBook#Nice_Mocks_and_Strict_Mocks

You could try to move your stuff out to a method in new owned/temporary object that doesn't suffer from this.

/Martin

Bogdan Spuze

unread,
Sep 11, 2012, 5:25:52 AM9/11/12
to googl...@googlegroups.com
Thanks for the information Martin.

I don't wanna do anything in the constructor(I used this terms because I thought that it would be easier to explain).

So. I have a mocked class. There are two functions in it:  Init() and Destroy().

Just wanna check that only after Init() is called then Destroy() will be called also.
Somethig like

if( Init() ) //if init() is called
EXPECT_CALL(mock_obj, Destroy()).Times(1);
else
EXPECT_CALL(mock_obj, Destroy()).Times(0);


Vlad Losev

unread,
Sep 11, 2012, 1:49:14 PM9/11/12
to Google C++ Mocking Framework
Google Mock is not well suited to representing complex dependencies like these. You may have to express them indirectly, e.g.:

ACTION_P2(Increment, counter, increment) { *counter += increment; }

int counter = 0;
EXPECT_CALL(mock_obj, Init())
    .WillRepeatedly(Increment(&counter, 1));
EXPECT_CALL(mock_obj, Destroy())
    .WillRepeatedly(Increment(&counter, -1));
EXPECT_EQ(0, counter);

HTH,
Vlad

Keith Ray

unread,
Sep 11, 2012, 1:59:33 PM9/11/12
to Vlad Losev, Google C++ Mocking Framework

So. I have a mocked class. There are two functions in it:  Init() and Destroy().

Just wanna check that only after Init() is called then Destroy() will be called also.
Somethig like

if( Init() ) //if init() is called
EXPECT_CALL(mock_obj, Destroy()).Times(1);

Think of tests as executable examples. You can assert that init & destroy were called in an example run; but, asserting that destroy is _never_ called unless init has been called isn't a good example for a test. Code review should be enough to verify a "never" condition.

Martin Svensson

unread,
Sep 11, 2012, 3:13:50 PM9/11/12
to googl...@googlegroups.com
On 2012-09-11 11:25, Bogdan Spuze wrote:
> Thanks for the information Martin.
>
> I don't wanna do anything in the constructor(I used this terms because
> I thought that it would be easier to explain).
>
> So. I have a mocked class. There are two functions in it: Init() and
> Destroy().
>
> Just wanna check that only after Init() is called then Destroy() will
> be called also.
> Somethig like
>
> if( Init() ) //if init() is called
> EXPECT_CALL(mock_obj, Init()).Times(1);
> else
> EXPECT_CALL(mock_obj, Destroy()).Times(0);

Ok, Bogdan,

If you make it a StrictMock, it fails on unexpected calls. Something
like this (not tried):

class MyMock
{
MOCK_METHOD0(Init);
MOCK_METHOD0(Destroy);
};

class MyFake:
public testing::StrictMock <MyMock>
{
void expectInitAndDestroy() { EXPECT_CALL(*this,
Init()).WillOnce(InvokeWithoutArgs(this, expectDestroy)); }
void expectDestroy() { EXPECT_CALL(*this, Destroy()); }
};

TEST(TargetIsDestroyedAfterInit)
{
MyFake myFake;
myFake.expectInitAndDestroy();
MyObject myObject(myFake);
}


But fakes do not make Good Unit Tests (GUTs). It's much better to just
expect both calls from the test case.

TEST(TargetIsInitedAndDestroyed)
{
MyFake myFake;
{
testing::InSequence;
myFake.expectInit();
myFake.expectDestroy();
}
MyObject myObject(myFake);
}


/Martin Svensson

Bogdan Spuze

unread,
Sep 12, 2012, 9:14:58 AM9/12/12
to googl...@googlegroups.com
Hello,

Thanks again for the tips and help.
I adapted Martin's example to my code and now it works as intended.

I did  something like:

ExpectDestroy()
{
    EXPECT_CALL(my_mock, DestroyEntry(_)).Times(1);
}

TEST(TestMyMock, TestInitDestroy)
{
   EXPECT_CALL(my_mock,CreateEntry()).Times(AtMost(1)).WillRepeatedly(Invoke(ExpectDestroy));
   myRealObject->DoStuff(); //here my mocked object is created and hopefully destroyed :D 
   Mock::VerifyAndClearExpectations(my_mock);
}

Thanks a lot again!

Have a nice day!

Bogdan

Vlad Losev

unread,
Sep 13, 2012, 1:02:05 PM9/13/12
to Google C++ Mocking Framework
On Wed, Sep 12, 2012 at 6:14 AM, Bogdan Spuze <bogdan...@gmail.com> wrote:
Hello,
Thanks again for the tips and help.
I adapted Martin's example to my code and now it works as intended.

I did  something like:

ExpectDestroy()
{
    EXPECT_CALL(my_mock, DestroyEntry(_)).Times(1);
}

TEST(TestMyMock, TestInitDestroy)
{
   EXPECT_CALL(my_mock,CreateEntry()).Times(AtMost(1)).WillRepeatedly(Invoke(ExpectDestroy));

I 'd like to point that such code is explicitly disavowed by Google Mock documentation as undefined behavior (see http://code.google.com/p/googlemock/wiki/ForDummies#Using_Mocks_in_Tests). It may work in this particular situation and/or with the current library version but don't rely on it in general.

Bogdan Spuze

unread,
Sep 18, 2012, 4:08:07 AM9/18/12
to googl...@googlegroups.com
Hello there,

Thanks for pointing that out.
I'll try a work-around.
Reply all
Reply to author
Forward
0 new messages