When you declare an abstract class in C++, it looks like this:
class AbstractClass
{
public:
virtual int ReturnFive() = 0;
};
in Microsoft’s world you have an additional choice – declare a pure virtual method using the PURE macro (basically equivalent):
class AbstractClass
{
public:
virtual int ReturnFive() PURE;
};
Here are the guidelines on how to fake an abstract type. In any case – you don’t need to touch your production code.
If possible, fake a concrete class that is already defined in your production code. For example, if that’s your concrete class:
1 |
<font face="Consolas"><span><font color="#0000ff">class</font></span><font color="#000000"> ConcreteClass : </font><span><font color="#0000ff">public</font></span></font><font face="Consolas"><font color="#000000"> AbstractClass<br />{<br /></font><span><font color="#0000ff"><font color="#000000"> </font>virtual</font></span><font color="#000000"> </font><span><font color="#0000ff">int</font></span><font color="#000000"> ReturnFive() {</font><span><font color="#0000ff">return</font></span><font color="#000000"> 0;};<br />};</font></font> |
The test looks like that:
TEST_F(AbstractClassTests, FakingPureMethodUsingConcreteClass)
{
AbstractClass* abstractClass = FAKE<ConcreteClass>();
WHEN_CALLED(abstractClass->ReturnFive()).ReturnVal(5);
ASSERT_EQ(5, abstractClass->ReturnFive());
}
If you don’t have a concrete type definition handy do the following:
Derive a class from the abstract class, and define all the pure virtual methods as FAKED. You don’t need to define other methods in the derived class. This class is for testing only, so you don’t need to change your production code. Just define it in your test project.
1 |
<font face="Consolas"><span><font color="#0000ff">class</font></span><font color="#000000"> DerivedClass : </font><span><font color="#0000ff">public</font></span></font><font face="Consolas"><font color="#000000"> AbstractClass<br />{<br /></font><span><font color="#0000ff"><font color="#000000"> </font>virtual</font></span><font color="#000000"> </font><span><font color="#0000ff">int</font></span><font color="#000000"> ReturnFive() FAKED;<br />};</font></font> |
Once you define it, you can use it in your test like this:
1 |
<font color="#000000" face="Consolas">TEST_F(AbstractClassTests, FakingPureMethodUsingDerivedClass)<br />{<br /> AbstractClass* abstractClass = FAKE<<strong>DerivedClass</strong>>();<br /> WHEN_CALLED(abstractClass->ReturnFive()).ReturnVal(5);<br /> ASSERT_EQ(5, abstractClass->ReturnFive());<br />}</font> |
In both cases, we’re using the FAKE macro with the substitute: either the concrete class ConcreteClass or the derived definition DerivedClass, to return an AbstractClass pointer. From then on, it’s business as usual.