4

许多关于单元测试的网站都说要提取接口和接口代码(这是有道理的),但这需要通过指针使用多态性。是否可以在没有指针的情况下完成此操作,因此我不必修改生产代码?我宁愿不使用指针和管理内存。

  • 允许条件编译。
  • 我专门为我的存根/模拟使用 gmock。

我研究过的一些事情是:

  • 使用参考
    • 涉及编写特殊的复制构造函数或使其不可复制
    • 仍然需要用 new/delete 来管理内存
    • 不确定这是否会导致不可预见的问题
  • 通过代码生成创建指针包装类的集合。界面保持不变,但添加了一些测试方法。
    • 似乎它会工作,但需要保养
    • 我在下面的意思的例子

请注意 gmock 模拟对象是不可复制的,因此我不能构造函数注入它们。(https://groups.google.com/forum/#!topic/googlemock/GD73UXjQowE/discussion

问题示例

class Example
{
public:
   Example();
   ~Example();

private:
   // I want to stub out _foo.
   Dependency _foo;
};

指针包装类示例

#ifndef UNIT_TEST
   Foo _foo;
#else
   PtrWrapFoo _foo;
#endif

...

_foo.setImpl(StubFoo *aStubFoo);

...

void PtrWrapFoo::doSomething()
{
   _impl->doSomething();
}
4

2 回答 2

2

在过去,我Dependency在一个单独的编译单元中实现并链接到它而不是原来的。

这就是 Michael Feathers 所说的Link Seam

于 2013-04-17T13:47:32.287 回答
2

经过深思熟虑,我决定放弃这个想法。给定测试场景,尝试和管理依赖项应该使用特定实现(例如真实、模拟、假)的情况变得太困难了。

所有需要测试的依赖项现在都有接口,它们是无成员的。我的生产代码使用依赖项指针,如果我想要可测试的代码,这是我必须忍受的现实。在阅读了 Roy Osherove 的书《单元测试的艺术》后,我被说服了这个概念。我的常规构造函数实例化了真正的具体类。我还有额外的构造函数/设置器,它们为单元测试有条件地编译,因此我可以使用存根/模拟正确地设置依赖关系。

通过使用工具从类中提取接口,我减少了编写额外代码的需要。

总体而言,新设计很好,并且以最小的开销充分回避了模拟非指针成员变量的问题。

于 2013-06-03T02:08:12.513 回答