2009-07-14 71 views
21

为了能够单元测试我的C++代码,我通常会传递被测试类的构造函数一个或多个可以是“生产代码”或假/模拟对象的对象(让我们调用这些注射物体)。我已通过C++中用于依赖注入的接口vs模板

  1. 创建了“生产代码”类和假/模拟类继承的接口。
  2. 使被测试的类成为模板类,该类将注入对象的类型作为模板参数,并将注入对象的实例作为参数传递给构造函数。

一些随机的想法:

  • ,直到我们有概念(C++ 0x中),只有文件和参数的命名会提示什么提供被测类(使用模板时)。
  • 它并不总是能够创造遗留代码的接口
  • 的接口基本上只创建能够做到依赖注入
  • 以同样的方式:模板测试类只是做使依赖注入

你有什么想法?这个问题还有其他解决方案吗?

回答

4

我觉得界面选项比较好,但是不需要为了测试而创建公共基类。您可以从生产类继承您的模拟类并覆盖必要的方法。你必须使这些方法变得虚拟,但这就是mockpp这样的工具的工作原理,它们也允许将这个过程自动化一点点。

+0

这很简单,但非常强大。我喜欢! – 2009-07-15 14:48:11

+4

为了记录,人们应该意识到使方法变为虚拟问题(参见非虚拟接口(NVI)习语) – 2009-08-29 23:10:34

+1

是的,有时这种方法可能会与“纯粹的NVI”发生冲突。在很多情况下,你可以嘲笑受保护的虚拟函数,但是如果你确实需要模拟公共的非虚拟接口,那么我认为它不会让公众虚拟化,并且仍然使用NVI。在这种情况下,人们会失去一些编译器执行的最佳实践,但本身并不是最佳实践。 – 2009-09-01 22:57:55

8

用C++,还有另一种选择 - 你给你的mock类完全相同的名称作为真正的类,和链接单元测试时,只需用mock对象/库文件,而不是以假乱真将它们链接。

+1

理论上是。但我认为这在实践中不会很好。例如。你想在一次测试中模拟的班级可能会在另一次测试中被测试。然后,你需要为每个测试套件或类似的东西创建一个单独的项目(VS项目,例如)... – 2009-07-14 21:14:15

+1

非常多的是。我只是为了适应测试框架而对代码重大变化(例如接口和DI,即使它们没有真正意义的地方)有很强烈的反感。无论如何,我可以告诉你,这个方案在实践中确实有效(我已经看到它在生产中成功使用),尽管它需要更多样板 - 但至少它不在代码本身! – 2009-07-14 22:40:22

+0

我同意。我将不得不调查一下它对我们会造成的后果。也许一些魔法可以应用到VS项目中以使其更容易。 – 2009-07-15 14:55:10

3

模板将有运行时略少的性能损失(减少间接性,更少的电话,更多的在线优化),但将让你受苦了编译时间非常高的惩罚......

我认为,为了这个目的,接口更好(直到我们在C++ 0x TR1中有概念)......除非你不能减慢一些“瓶颈代码”。接口在运行时更具动态性和可切换性。

记住,你可以构造具有默认的注射对象(以假乱真)类,但你可以有注入你的测试模拟那些工厂......你甚至都不需要继承。

+1

能否详细说明最后一段?你会如何使用工厂来注入模拟对象? – 2009-07-15 14:56:30

+0

http://msdn.microsoft.com/en-us/magazine/cc163739.aspx – 2009-07-16 20:43:09

+1

简而言之:您可以拥有一个创建所有内部所需对象的单体工厂,并且您可以将该工厂替换为创建模拟工厂对象在你的测试中 – 2009-07-16 20:44:59

2

不知道是否有帮助,但你可以有模板的构造函数:

struct Class_Under_Test 
{ 
    template <typename Injected> 
    Class_Under_Test() 
    { 
     ... 

    // and even specialize them 
    template <> 
    Class_Under_Test <A_Specific_Injection_Class> 
    { 
     ... 

只有实际使用会得到包括一个。