【问题标题】:C++ and Dependency Injection in unit testing单元测试中的 C++ 和依赖注入
【发布时间】:2010-04-09 18:04:12
【问题描述】:

假设我有一个像这样的 C++ 类:

class A
{
    public:
        A()
        {

        }

        void SetNewB( const B& _b ) { m_B = _b; }

    private:
        B m_B;
}

为了对这样的东西进行单元测试,我必须打破 A 对 B 的依赖。由于类 A 持有一个实际对象而不是指针,我将不得不重构这段代码以获取一个指针。此外,我需要为 B 创建一个父接口类,这样我就可以在测试 SetNewB 时传入我自己的假 B。

在这种情况下,使用依赖注入进行单元测试不会使现有代码进一步复杂化吗?如果我将 B 设为指针,我现在将引入堆分配,并且现在有一些代码负责清理它(除非我使用 ref 计数指针)。此外,如果 B 是一个相当简单的类,只有几个成员变量和函数,为什么要为它引入一个全新的接口而不是只使用 B 的实例进行测试?

我想您可以提出使用接口重构 A 会更容易的论点。但是在某些情况下,两个类可能需要紧密耦合吗?

【问题讨论】:

    标签: c++ unit-testing dependency-injection


    【解决方案1】:

    我认为您对单元测试的想法太过分了。在这种情况下,A 和 B 是一个单元,即 A 不能没有 B 存在。首先,测试 B 并确保它通过所有 B 特定的单元测试,然后一旦通过,测试 A 并确保它表现出应有的样子。

    【讨论】:

    • 有趣,我想我是在想象单元测试要求所有类之间完全解耦。但是正如您所指出的,A 绝对需要 B 才能工作;所以它们实际上是一个单元。
    【解决方案2】:

    如果B 确实是注入A 的依赖项,那么您应该考虑一些其他选项。首先是在构建时注入B

    class A
    {
        public:
            A( const B& _b ) : m_B(_b) {}
    
        private:
            const B& m_B;
    };
    

    如果您真的想在 A 对象的生命周期内修改 B,那么问问自己您是否真的是 B 的所有者。如果不是,则传递一个指向它的指针并假设传递它的人负责它的生命周期——尽管这是一条棘手的路线,并且可能需要您使用 ref-counted 指针。

    如果您想要为自己获取 B 的副本,那么您可以在 B 上定义一个 clone() 方法。如果您想使用 B 中包含的信息创建自己的对象,那么您可以在构造函数中注入 MyBFactory 并将其与 B 一起使用。

    【讨论】:

      【解决方案3】:

      根据您使用 B 的方式,您可以使用 std::auto_ptr 而不是引用计数指针。只要您不需要将对 B 的引用传递给其他可以工作且需要最少代码更改的东西。

      【讨论】:

        猜你喜欢
        • 2018-03-03
        • 2021-06-19
        • 1970-01-01
        • 2017-11-03
        • 2016-02-16
        • 2010-10-23
        • 2017-04-01
        相关资源
        最近更新 更多