How can I mock a class when the code will dynamic_cast it to another class?

592 views
Skip to first unread message

Roger Li

unread,
Oct 31, 2011, 7:53:40 PM10/31/11
to Google C++ Mocking Framework
Hello,

I am trying to implement google test/mock on the legacy code and here
is an interesting situation that I don't know how can I create my
mock class.

Assuming in the legacy code there is a base class Car which is a
concrete class unfortunately. And then there is a sub class of the Car
called SUV

class SUV : public Car
{
public:
void setAwdMode(); // not a virtual method either, this method
doesn't exist in class Car
....
}

Then I want to unit test the method driveInSnow in a class
DrivingSystem :
class DrivingSystem
{
public:
void driveInSnow(Car& aCar); // not a virtual method either :(
...
}

The implementation of driveInSnow() looks like this:
void DrivingSystem::driveInSnow(Car& aCar)
{
SUV& aSuv = dynamic_cast<Car&>(aCar);
if (&aSuv != NULL)
{
aSuv.setAwdMode();
}
....
}

I want to create a mock of "aCar" to be able to simulate setAwdModel()
method. Since this method is not virtual, I have to change the
driveInSnow() to be a template method:
template<typename Car>
void DrivingSystem::driveInSnow(Car& aCar) {}

But it won't satisfied the dynamic_cast as the mock class has nothing
to do with Suv. To be able to be a "Suv" I create a mock class like
this:
class MockSuv : public Suv
{
MOCK_METHOD0(setAwdMode, void());
}

But the mocked method won't get called because the Suv::setAwdMode()
is not virtual!

So... what I can do for this situation and how can I test the code?

Thanks in advance,
Roger

Roger Li

unread,
Oct 31, 2011, 8:35:29 PM10/31/11
to Google C++ Mocking Framework
Sorry, in the previous example, the dynamic_cast should be

SUV& aSuv = dynamic_cast<SUV&>(aCar);

Roger

Greg Miller

unread,
Oct 31, 2011, 9:16:09 PM10/31/11
to Roger Li, Google C++ Mocking Framework
Hi, Roger.

The short and hacky answer is to make Car::setAwdMode() virtual if possible, then mock it as you described. This is obvious and I'm sure you thought of it.

The long—and personally recommended—answer is to refactor the legacy code so that it's designed better and Designed for Testability. There are lots of smells in the legacy code you described that indicate a broken object model and poor design, such as the dynamic casting to simulate a crude polymorphism. Even if you get past this current stumbling block, there will be another, maybe more painful, one following it.

Only you know the full scope and context of your situation. But if the legacy code is worth testing, it's probably worth refactoring. My experience and intuition says that the investment usually pays off. But that's all just my opinion.

Greg
Reply all
Reply to author
Forward
0 new messages