2016-11-09 48 views
1

此问题来自一个真实世界的项目,该项目使用“经常在基类中提供受保护的接口”模式。重构受保护的基类依赖项测试

这里有一个小例子:

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 
    } 
}; 

我在寻找一种快速,无创大多重构,以取代的GetValue依赖。 提取方法和添加新的类允许HeavyWeightClassIWantToTest

@UPDATE:测试,来说明这个问题

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

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

提示:目前,我们正在使用的接头缝更换UntouchableBase执行用于测试目的。

请提供编码示例。

+0

老虎屁股摸不得是'UntouchableBase'?你可以修改头文件,甚至没有?那么'class TestableBase:public UntouchableBase',然后从'TestableBase'派生'HeavyWeightClass'? –

+0

UntouchableBase的变化成本非常高。您不能直接重载,因为GetValue()方法不是虚拟的。 – mrAtari

+0

我认为你的意思是“重写”而不是“重载”,但是假如没有人在做'pUntouchableBase-> GetValue()',你可以用中间类中的版本来隐藏函数。 –

回答

0

蛮力的解决办法是: #define protected public

更清洁机制,是使UntouchableBase的考验的朋友。这允许测试代码(以及测试代码)访问私有,受保护的,同时保护它们免受其他一切的影响。

什么人应该做的是使用编译器定义单元测试:

#ifdef UNIT_TESTING 
friend void UnitTestFn() 
#endif 

如果您使用的是谷歌测试,你可以使用FRIEND_TEST申报测试fixtue作为测试的朋友可以关注类。

+0

根本没有帮助。如何替换GetValue调用? – mrAtari

1

你有模板的方法:

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>; 
+0

+1'this->'overload!不幸的是,在生产代码中创建HeavyWeightClass是由系统完成的。许多HeavyWeight类都以相同的方式处理。 – mrAtari