mrAtari
mrAtari

Reputation: 650

Refactor protected base class dependency for test

This problem comes from a real world project, which uses the "provide protected interface in base class" pattern very often.

Here's a small example:

class UntouchableBase
{
protected: //cannot be called from outer class
    int GetValue() { return 42;}//not virtual

    //this class has many many more "protected interface" methods
};

class HeavyWeightClassIWantToTest: public UntouchableBase
{
public:
//  VeryHeavyClassIWantToTest(...) {} //ignore the creation issue for a heavy weight object here

    void MethodThatNeedsTest()
    {
        //calc some values
        int result = GetValue(); 
        //do some other stuff
    }
};

I'm looking for a fast, mostly noninvasive refactoring, to replace the GetValue dependency. Extracting Methods and adding new class is allowed for HeavyWeightClassIWantToTest

@UPDATE: Test,to illustrate the issue

TEST(EnsureThat_MyMethodThatNeedsTestDoesSthSpecial)
{
    HeavyWeightClassIWantToTest sut = MakeSut();

    sut.MethodThatNeedsTest(); //should call a mocked / replaced GetValue()
}

Hint: Currently we're using a linker seam to replace the UntouchableBase implementation for testing purposes.

Please provide coded examples.

Upvotes: 1

Views: 60

Answers (2)

Jarod42
Jarod42

Reputation: 217950

You have the template way:

template <typename Base>
class HeavyWeightClassIWantToTestGeneric: public Base
{
public:
    // ...

    void MethodThatNeedsTest()
    {
        //calc some values
        int result = this->GetValue(); // use `this->` for dependent name
        //do some other stuff
    }
};

// For production
using HeavyWeightClassProduction = HeavyWeightClassIWantToTestGeneric<UntouchableBase>;

// For Test
using HeavyWeightTest = HeavyWeightClassIWantToTestGeneric<TestBase>;

Upvotes: 1

N.A.
N.A.

Reputation: 1489

The brute-force solution could be: #define protected public

More cleaner mechanism is to make the test friend of the UntouchableBase. This allows the test code (and just the test code) access to the privates, protecteds, whilst protecting them from everything else.

What one should do is use a compiler define for unit testing:

#ifdef UNIT_TESTING
friend void UnitTestFn()
#endif

If you are using Google Test, you can use FRIEND_TEST to declare your test fixtue as a friend to the class under test.

Upvotes: 0

Related Questions