类Foo公共函数改为protected后,如何低成本兼容旧测试代码?
你的方案可行,还有更简洁的替代方案
先给你肯定:继承方案完全能用
你说的创建公开继承Foo的派生类,把基类的protected旧函数重新包装成public的方案,完全能解决问题。举个实际代码例子:
// 原业务类,旧函数已改为protected class Foo { protected: void old_func1() { /* 原有实现 */ } void old_func2() { /* 原有实现 */ } // ...其他旧函数 }; // 测试专用的派生类 class TestableFoo : public Foo { public: // 把基类的protected函数转成public void old_func1() { Foo::old_func1(); } void old_func2() { Foo::old_func2(); } // 对应所有需要测试的旧函数都做一次转发 }; // 测试代码里直接换用TestableFoo对象 TestableFoo foo; foo.old_func1(); // 原来的调用代码完全不用改,编译正常
这个方案的好处是完全不碰原Foo类的代码,不会影响业务逻辑的封装,测试代码只需要把原来的Foo对象声明改成TestableFoo就行,函数调用部分原封不动。
更优的方案:给测试代码加友元授权
如果你能接受给原Foo类加几行条件编译的代码,友元授权是更省心的选择——测试代码连对象类型都不用改,直接用原来的Foo对象调用旧函数就行。
两种友元实现方式
1. 给测试类加友元
在Foo里只允许你的测试类访问protected成员,用条件编译确保生产代码不会看到这段友元声明:
// 原Foo类 #ifdef TEST_ENV // 只在测试环境编译这段 class FooTestSuite; // 提前声明你的测试类 #endif class Foo { #ifdef TEST_ENV friend class FooTestSuite; // 授权测试类访问所有protected成员 #endif protected: void old_func1() { /* 原有实现 */ } void old_func2() { /* 原有实现 */ } }; // 测试代码里的测试类 class FooTestSuite { public: void run_all_tests() { Foo foo; foo.old_func1(); // 直接调用protected函数,完全不用改原来的测试代码 foo.old_func2(); } };
2. 给单个测试函数加友元
如果你的测试没有统一的测试类,也可以直接给需要调用旧函数的测试函数加友元:
// 原Foo类 #ifdef TEST_ENV void test_old_func1(); void test_old_func2(); #endif class Foo { #ifdef TEST_ENV friend void test_old_func1(); friend void test_old_func2(); #endif protected: void old_func1() { /* 原有实现 */ } void old_func2() { /* 原有实现 */ } }; // 测试函数 void test_old_func1() { Foo foo; foo.old_func1(); // 直接调用 }
两种方案怎么选
- 如果你绝对不想修改原Foo类,就用派生类方案,虽然要写个小类,但对业务代码零侵入;
- 如果你能接受加几行条件编译的友元声明,友元方案更高效——测试代码几乎不用改,省了替换对象类型的功夫。
内容的提问来源于stack exchange,提问作者DevEkalavya
相关产品推荐
相关产品推荐

