C+中依赖注入的接口与模板+; >为了能够对我的C++代码进行单元测试,我通常通过被测试类的构造函数,或者可以是“生产代码”或假的/模拟对象的几个对象(我们调用这些注入对象)。我也曾经这样做过 创建“生产代码”类和fake/mock类都继承的接口 使被测类成为一个模板类,该模板类将注入对象的类型作为模板参数,并将注入对象的实例作为构造函数的参数

C+中依赖注入的接口与模板+; >为了能够对我的C++代码进行单元测试,我通常通过被测试类的构造函数,或者可以是“生产代码”或假的/模拟对象的几个对象(我们调用这些注入对象)。我也曾经这样做过 创建“生产代码”类和fake/mock类都继承的接口 使被测类成为一个模板类,该模板类将注入对象的类型作为模板参数,并将注入对象的实例作为构造函数的参数,c++,unit-testing,mocking,C++,Unit Testing,Mocking,一些随意的想法: 在我们有了概念(C++0x)之前,只有文档和参数命名会提示要为测试中的类提供什么(当使用模板时) 并非总是可以为遗留代码创建接口 接口的创建基本上只是为了能够进行依赖项注入 以同样的方式:对测试中的类进行模板化只是为了启用依赖项注入 你的想法是什么?对于这个问题还有其他的解决方案吗?< P> C++,还有一个选项——你给模拟类和真实的类完全相同的名字,当连接你的单元测试时,只需将它们与模拟对象/库文件链接而不是真实的。但不必仅仅为了测试而创建公共基类。您可以从生产类继承模拟

一些随意的想法:

  • 在我们有了概念(C++0x)之前,只有文档和参数命名会提示要为测试中的类提供什么(当使用模板时)
  • 并非总是可以为遗留代码创建接口
  • 接口的创建基本上只是为了能够进行依赖项注入
  • 以同样的方式:对测试中的类进行模板化只是为了启用依赖项注入

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

< P> C++,还有一个选项——你给模拟类和真实的类完全相同的名字,当连接你的单元测试时,只需将它们与模拟对象/库文件链接而不是真实的。但不必仅仅为了测试而创建公共基类。您可以从生产类继承模拟类并重写必要的方法。不过,您必须使这些方法虚拟化,但这就是像这样的工具的工作方式,它们还允许稍微自动化这一过程。

模板对运行时的性能影响会稍微小一些(间接操作更少,调用更少,内联优化更多),但会使您在编译时间上受到非常高的影响

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


请记住,您可以使用默认注入对象(真实对象)构造类,但您可以在测试中使用工厂注入模拟对象。。。您甚至不需要子类化。

不知道它是否有用,但您可以使用模板构造函数:

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

    // and even specialize them
    template <>
    Class_Under_Test <A_Specific_Injection_Class>
    {
        ...
struct Class\u正在测试中
{
模板
测试()下的类别
{
...
//甚至专门化它们
模板
测试中的类别
{
...

只有实际使用的类才会被包括在内。

理论上是的。但我认为这在实践中并不好。例如,你想在一个测试中模拟的类可能会在另一个测试中测试。然后你需要创建一个单独的项目(VS project,例如)对于每一个测试套件或类似的东西……几乎是的。我只是非常反感仅仅为了适应测试框架而进行的重大代码更改(例如到处都是接口和DI,即使它们没有实际意义)。无论如何,我可以告诉你,这个方案在实践中确实有效(我已经看到它成功地用于生产),尽管它确实需要更多的样板文件,但至少它不在代码中!我同意。我将不得不做一些调查,看看它会给我们带来什么样的后果。也许可以在VS项目中应用一些魔法来简化它。这是一个有趣的方法,也让我更感兴趣“C++-like”与其他解决方案不同,这些解决方案要么需要某种性能的提升(无论多么轻微),要么需要臃肿的代码。这很简单,但确实很强大。我喜欢它!只是为了记录在案,人们应该意识到将方法虚拟化存在一些问题(参见非虚拟接口(NVI)习惯用法)是的,有时这种方法会与“纯粹的NVI”相冲突"。在许多情况下,您可以仅模拟受保护的虚拟函数,但如果您确实需要模拟公共非虚拟接口,我认为将其设置为公共虚拟接口并仍然使用NVI不会造成太大的伤害。在这种情况下,编译器会失去一些最佳实践的强制执行,但最佳实践本身不会。这并非总是可能的安全地从生产类继承:例如,如果构造函数有副作用,或者它的数据字段干扰了测试代码不应触及的外部事物。你能详细说明最后一段吗?你将如何使用工厂注入模拟对象?简言之:你可以有一个创建模拟对象的单例工厂所有您内部需要的对象,并且您可以用在测试中创建模拟对象的工厂替换此工厂