Mocking a Base class

3,663 views
Skip to first unread message

Neha Jain

unread,
Jul 10, 2010, 1:48:22 PM7/10/10
to Google C++ Mocking Framework
Hi,

I am trying to mock a base class used in my code. I havent seen any
examples and am wondering if its possible.

Element is the base class that I am trying to Mock. The class
UTManager originally inherits from Element. I have now changed it to
inherit from MockElement, since I want certain functions to be
mockable... not sure if I am doing the right thing.

My code:

class MockElement: public Element{
public:
MockElement():Element(){}

virtual ~MockElement(){}

MOCK_METHOD3(StartTimer, void(TimerId timerId, TimerDuration
timerDuration, bool bPeriodic));

};


TEST_F(TestElementMock, TEST_StartTimer)
{
MockElement* mockElement = new MockElement();

EXPECT_CALL(*mockElement, StartTimer(_,_,_))
.Times(AtLeast(1));

UTManager* pUTManager = new UTManager(); // UTManager inherits
from MockElement now
pUTManager->Initialize(); // The initialize method makes a call to
StartTimer
pUTManager->HandleTimeout(12);

delete mockElement;
}


When I run, I get the following:

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TestElementMock
[ RUN ] TestElementMock.TEST_StartTimer

GMOCK WARNING:
Uninteresting mock function call - returning directly.
Function call: StartTimer(12, 20, false)
Stack trace:

GMOCK WARNING:
Uninteresting mock function call - returning directly.
Function call: StartTimer(12, 20, false)
Stack trace:
TestElementMock.cpp:30: Failure
Actual function call count doesn't match EXPECT_CALL(*mockElement,
StartTimer(_,_,_))...
Expected: to be called at least twice
Actual: never called - unsatisfied and active
Test run.
[ FAILED ] TestElementMock.TEST_StartTimer (1 ms)
[----------] 1 test from TestElementMock (1 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] TestElementMock.TEST_StartTimer


Any help will be appreciated.
Thanks!
Neha

Dean Sturtevant

unread,
Jul 10, 2010, 3:09:11 PM7/10/10
to Neha Jain, Google C++ Mocking Framework
It seems you are creating 2 MockElements and setting expectations on
one, but invoking the other. Place the expectations on the object you
are using.
- Dean

Neha Jain

unread,
Jul 10, 2010, 3:21:10 PM7/10/10
to Dean Sturtevant, Google C++ Mocking Framework
Hi Dean,

Thanks for the reply. What you are saying makes sense. But I guess I do not know how to access the mock element which is the base class of UTManager.
Maybe what I am trying to do is not possible.

Thanks

Remco Teunen

unread,
Jul 10, 2010, 3:33:16 PM7/10/10
to Neha Jain, Google C++ Mocking Framework
Hi Neha,

The problem with your particular test is that you should set the expectation on pUTManager, not mockElement. mockElement isn't used anywhere. Try this:

TEST_F(TestElementMock, TEST_StartTimer)
{
   UTManager* pUTManager = new UTManager(); // UTManager inherits from MockElement now

   EXPECT_CALL(*pUTManager, StartTimer(_,_,_))
       .Times(AtLeast(1));

   pUTManager->Initialize(); // The initialize method makes a call to StartTimer
   pUTManager->HandleTimeout(12);

   delete pUTManager;
}

However, instead of having UTManager inherit from a mock, why not just use a partial mock for UTManager itself? In other words, use the following mock:

class MockUTManager : public UTManager {
 public:
   MOCK_METHOD3(StartTimer, void(TimerId timerId, TimerDuration
      timerDuration, bool bPeriodic));
};

And then you would use MockUTManager in your test. This is generally the way to go.

Good luck!
Remco

Tyler Ross

unread,
Jul 12, 2010, 11:05:55 AM7/12/10
to Neha Jain, Google C++ Mocking Framework
Hi Neha,

The way I've typically seen mocks used is when implementing dependency injection. So in your case, it would be when you are testing an object that uses a UTManager; something like:

class TestedObject {
  TestedObject(Element* ut_manager);
  ...
}

In your production code, you would pass a real UTManager:

  ...
  TestedObject tested_object(new UTManager);
  ...


Then, in the test infrastructure, you would pass the mock version:

TEST_F(myTest, foo) {
  TestedObject tested_object(new MockElement);

   ...
}


However, it could be that what you actually need to do in this case is change UTManager so that the dependency or dependencies represented by 'Element' is dependency-injected rather than a base class;

class UTManager {
  UTManager(Element* element);

  ...
 private:
  Element* element_;
}

Then your test would be something like:

TEST_F(TestElementMock, TEST_StartTimer)
{
   MockElement* mockElement = new MockElement();

   EXPECT_CALL(*mockElement, StartTimer(_,_,_))
       .Times(AtLeast(1));

   UTManager* pUTManager = new UTManager(mockElement);
   pUTManager->Initialize();
   pUTManager->HandleTimeout(12);

   delete mockElement;
}

Cheers,
Tyler

On Sat, Jul 10, 2010 at 10:48 AM, Neha Jain <nehaj...@gmail.com> wrote:



--
Tyler Ross | Software Engineer | Google - Apps - Postini

Neha Jain

unread,
Jul 12, 2010, 3:21:56 PM7/12/10
to Tyler Ross, Google C++ Mocking Framework
Thanks for your responses Tyler and Remco.
Unfortunately, I cant change the code in this scenario, but will sure keep 'dependency injection' in mind in future.
Reply all
Reply to author
Forward
0 new messages