【问题标题】:How do you mock classes that use RAII in c++你如何在 C++ 中模拟使用 RAII 的类
【发布时间】:2010-09-16 18:39:46
【问题描述】:

这是我的问题,我想模拟一个在初始化时创建线程并在销毁时关闭它的类。我的模拟类没有理由实际创建和关闭线程。但是,为了模拟一个类,我继承了它。当我创建模拟类的新实例时,会调用基类构造函数,从而创建线程。当我的模拟对象被销毁时,基类析构函数被调用,试图关闭线程。

如何在不处理实际资源的情况下模拟 RAII 类?

【问题讨论】:

    标签: c++ unit-testing mocking


    【解决方案1】:

    您改为创建一个描述类型的接口,并让真实类和模拟类都继承自该接口。所以如果你有:

    class RAIIClass {
     public:
      RAIIClass(Foo* f);
      ~RAIIClass();
      bool DoOperation();
    
     private:
      ...
    };
    

    你会做一个这样的界面:

    class MockableInterface {
     public:
      MockableInterface(Foo* f);
      virtual ~MockableInterface();
      virtual bool DoOperation() = 0;
    };
    

    然后从那里出发。

    【讨论】:

    • 具体去哪里? RAII 类通常按值使用,而不是在堆上分配。它们主要用于处理堆栈上的堆对象以获得确定的生命周期。 Example
    【解决方案2】:

    首先,您的类可能为它们的使用而设计得很好,但为测试而设计得不好,这不一定是不合理的事情。并非所有东西都易于测试。

    大概您想使用另一个函数或类来使用您要模拟的类(否则解决方案是微不足道的)。让我们称前者为“用户”,后者为“Mocked”。以下是一些可能性:

    1. 将用户更改为使用 Mocked 的抽象版本(您可以选择要使用的抽象类型:继承、回调、模板等......)。
    2. 为您的测试代码编译不同版本的 Mocked(例如,在您编译测试时 #def out the RAII code)。
    3. 已模拟接受构造函数标志以关闭其行为。我个人会避免这样做。
    4. 只是吸收分配资源的成本。
    5. 跳过测试。

    如果您不能修改 User 或 Mocked,最后两个可能是您唯一的办法。如果您可以修改 User 并且您认为设计可测试的代码很重要,那么您应该在其他任何选项之前探索第一个选项。请注意,在使代码通用/灵活和保持简单之间可以进行权衡,这两者都是令人钦佩的品质。

    【讨论】:

      【解决方案3】:

      pimpl 成语可能也适合您。创建您的 Thread 类,并在其下方引入具体实现。如果您输入正确的#defines 和#ifdefs,您的实现可能会在您启用单元测试时发生变化,这意味着您可以根据您要完成的任务在真实实现和模拟实现之间切换。

      【讨论】:

        【解决方案4】:

        我使用的一种技术是使用某种形式的装饰器。您的最终代码有一个方法,该方法在堆栈上创建其实例,然后调用相同的方法,但在一个成员上,该成员是指向您的基类的指针。当该调用返回时,您的方法返回销毁您创建的实例。

        在测试时,您交换一个不创建任何线程的模拟,而只是转发到您要测试的方法。

        class Base{
         protected:
          Base* decorated;
         public:
          virtual void method(void)=0;
        };
        class Final: public Base{
          void method(void) { Thread athread; decorated->method(); } // I expect Final to do something with athread
        };
        class TestBase: public Base{
          void method(void) { decorated->method(); }
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-05-18
          • 2010-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多