Best way to test a complex constructor?

6,102 views
Skip to first unread message

TTGator

unread,
Dec 10, 2010, 11:11:11 AM12/10/10
to Google C++ Mocking Framework
I'm just getting started with mock objects, and would like some advice
on the best way to unit test some particular code. I'm using Google
Test and Google Mock.

We have some legacy C++ code, although much of it is written like C.
I have a class (MyClass) with a constructor that does a LOT of crap in
it, I'll try to make this explanation brief: I created a new
InitMyPart function to replace a small section of the constructor in
hopes to make unit testing easier. I made it a virtual function...
but what it seems like I need to do is to make the CONSTRUCTOR
virtual, so that when I create the object, the constructor won't
execute the rest of the crap that's in there, and I can just call my
new function?

Am I on the right track? When you create a mock object in your test
class, I assume it would try to call the constructor it inherited from
by default right? That's what I need to get around I guess. Any help
much appreciated!

Manuel Klimek

unread,
Dec 10, 2010, 11:25:06 AM12/10/10
to TTGator, Google C++ Mocking Framework

Two options come to mind:
- create a new constructor in MyClass (perhaps private, and have the
test be a friend) that leaves the state of the class uninitialized
- pull out some of the code into a different class MyClassInnards,
pass MyClassInnards to MyClass in the constructor and have the
constructor call virtual methods on MyClassInnards - then you can mock
MyClassInnards instead of MyClass

Cheers,
/Manuel

Dean Sturtevant

unread,
Dec 10, 2010, 11:31:33 AM12/10/10
to Manuel Klimek, TTGator, Google C++ Mocking Framework
Note that if the base class calls a virtual function in its
constructor, it's the base class's implementation that is used.

Would it help in your case to write a factory?

- Dean

TTGator

unread,
Dec 10, 2010, 11:43:11 AM12/10/10
to Google C++ Mocking Framework

On Dec 10, 11:25 am, Manuel Klimek <kli...@google.com> wrote:
For option one, it seems like it would be cleaner in the production
code to do the following (if it is possible): Override the constructor
in the mock class to have an empty constructor. Is that possible and/
or advisable?

TTGator

unread,
Dec 10, 2010, 11:47:57 AM12/10/10
to Google C++ Mocking Framework


On Dec 10, 11:31 am, Dean Sturtevant <dsturtev...@google.com> wrote:
> Note that if the base class calls a virtual function in its
> constructor, it's the base class's implementation that is used.
>
> Would it help in your case to write a factory?
>
> - Dean
>


I think that is fine here, because my intent was to make it virtual
only so I can call it from the mock class, and pass it whatever
parameters I want to test the function. Right?

Manuel Klimek

unread,
Dec 10, 2010, 11:49:53 AM12/10/10
to TTGator, Google C++ Mocking Framework

You can do the following:
class Base {
public:
// constructor doing lots of stuff
Base(<many arguments>);

protected:
// constructor leaving the object uninitialized
Base();
};

class MockBase : public Base {
public:
// Not technically needed
MockBase() : Base() {}
};

This requires the least change to your code. On the other hand, I
think the other options are much cleaner...

Cheers,
/Manuel

TTGator

unread,
Dec 10, 2010, 12:45:36 PM12/10/10
to Google C++ Mocking Framework


On Dec 10, 11:49 am, Manuel Klimek <kli...@google.com> wrote:
But can/should I do this:

class Base {
public:
// constructor doing lots of stuff
virtual Base(<many arguments>);

};

class MockBase : public Base {
public:
// Override Base constructor to do nothing
MockBase() : Base(<many arguments>) {}

};

Manuel Klimek

unread,
Dec 10, 2010, 12:49:53 PM12/10/10
to TTGator, Google C++ Mocking Framework

No. The additional Base() constructor is what you can use instead...

Cheers,
/Manuel

TTGator

unread,
Dec 10, 2010, 1:03:01 PM12/10/10
to Google C++ Mocking Framework


On Dec 10, 12:49 pm, Manuel Klimek <kli...@google.com> wrote:
OK, thanks!

Dean Sturtevant

unread,
Dec 10, 2010, 1:21:41 PM12/10/10
to TTGator, Google C++ Mocking Framework
I'm a little confused about your use case -- it might help to point to
actual code.
But it sounds to me like what you wanted to do was to make the
function protected, not virtual.
- Dean

TTGator

unread,
Dec 10, 2010, 2:19:04 PM12/10/10
to Google C++ Mocking Framework


On Dec 10, 1:21 pm, Dean Sturtevant <dsturtev...@google.com> wrote:
> I'm a little confused about your use case -- it might help to point to
> actual code.
> But it sounds to me like what you wanted to do was to make the
> function protected, not virtual.
> - Dean
>
> On Fri, Dec 10, 2010 at 11:47 AM, TTGator <asorg...@gmail.com> wrote:
>
> > On Dec 10, 11:31 am, Dean Sturtevant <dsturtev...@google.com> wrote:
> >> Note that if the base class calls a virtual function in its
> >> constructor, it's the base class's implementation that is used.
>
> >> Would it help in your case to write a factory?
>
> >> - Dean
>
> > I think that is fine here, because my intent was to make it virtual
> > only so I can call it from the mock class, and pass it whatever
> > parameters I want to test the function.  Right?
>
>

So it looked a little like this... (and yes, I know the error handling
is aweful... again... legacy code here)

MyClass::MyClass (int foo, int bar)
: m_SuspendSemaphore(0),
m_bSuspended(false),
m_phMainState(NULL),
m_phSubstate(NULL),
m_bShuttingDown(false),
m_phVersionNum(NULL),
m_phPreviousMode(NULL),
m_phSupportSettings(NULL),
m_pMessageFactory(MessageFactory::GetSoleInstance()),
m_pActiveMessage(NULL),
m_EventCountSemaphore(0),
m_pIllegalEvent(NULL),
m_TService(this),

{

...Code to register a bunch of services and handlers here that
would not exist during unit testing...

// Read values from the global configuration file
bool b_flag1;
bool b_flag2;
...

try
{
b_flag1 = ConfigSys::GetSoleInstance()-
>GetBoolValue(ConfigConstants::CFlag1);
b_flag2 = ConfigSys::GetSoleInstance()-
>GetBoolValue(ConfigConstants::CFlag2);
...
}
catch (ConversionError& ex)
{
ERROROUT(__PRETTY_FUNCTION__ << ": Caught Exception: " <<
ex.GetDesc() << endl);
}
catch (ItemDoesNotExist& ex)
{
ERROROUT(__PRETTY_FUNCTION__ << ": Caught Exception: " <<
ex.GetDesc() << endl);


// Initialize my stuff (this is where my actual code change was
made, in this huge ugly block, so I took this chunk of code and made
it a function
MyClass::InitMyPart(b_flag1, b_flag2);

...Lots more code here below, which some of it acts on the flags
read from the global config file...

... More code that instantiates hardware dependent stuff, hence
more of my need to mock...

} //MyClass

void MyClass::InitMyPart( bool b_flag1, bool b_flag2 )
{

... Code to create a table with the values of the flags...

}

TTGator

unread,
Dec 10, 2010, 2:37:02 PM12/10/10
to Google C++ Mocking Framework
Thinking about this more, it might make sense for me to make 'b_flag1'
and 'b_flag2' attributes of MyClass. This will allow me to put the
section of code that reads from the global config file into
InitMyPart(), as well as give me something to do an ASSERT against.
Reply all
Reply to author
Forward
0 new messages