对不适合提取为新 class 的私有方法进行单元测试的好方法是什么?

What is a good way to unit test private methods that are not suitable to be extracted as a new class?

粗略地说,我有一个 class 实现了一个只有一个 public 方法的线程 run。该方法进入循环,就像调度程序一样,一条一条地处理网络消息;像下面这样:

class WorkerThread {

  public:

    void run() {
      while (!b_shutdown) {
        message = getNextMessage();
        switch(message.type) {
          case WRITE:
            write();
          case READ:
            read();
          // ...
          // more cases to handle
        }
      }
    }


  private:

    void write() { /* logic to test */ }
    void read() { /* logic to test */ }
    // more private methods with logic that needs testing

    // some member variables
};

所以重点是我真的不想

  1. 将私有方法提取到另一个 class,因为从语义上讲它们是此 WorkerThread.
  2. 的一部分
  3. 制作方法 public,因为它们不会在 class.
  4. 之外的任何地方使用
  5. 跳过测试,因为正是这些方法实现了主要逻辑。

但是私有方法如何优雅地进行测试呢?

注:

  1. 可能还需要一些 public 方法来处理线程的启动和终止,但这不是这里要考虑的问题。
  2. 我认为这个问题不局限于c++,所以我也用更流行的静态类型Java标记它,以引起更多关注:P

简单地说:不要。针对 public 接口进行测试,仅此而已。最终,这是唯一重要的事情。

如果您想查看它是否正常工作,应该通过 IoInterface 访问 read/write 函数,可以模拟它进行测试。

引用问题:

I really don't want to extract the private methods out to another class, because semantically they are part of this WorkerThread.

那是错误的。您违反了 Single Responsibility Principle

提供 "multi threading support" 和 "doing actual work" 是 两个 不同的东西。您应该 而不是 强制 "doing the actual work" 是私有实现细节。

从这个意义上说:您为自己制定的规则实际上导致您编写难以测试 代码。因此,与其 "working around" 糟糕设计的症状 - 不如退后一步,修复 您的设计。

换句话说:

  • 重做你的工作线程以能够运行任何类型的工作
  • 单独关注;并将 "this kind of work" 放入专门的 class

这样做,不仅会改进您的设计,还会使测试更容易:因为现在,您可以进行单元测试 "doing the actual work" 而无需 多线程的复杂性。您只需断言这些东西在按顺序完成时有效。然后你自己测试多线程部分;无需担心实际工作。最后,一切都很好地结合在一起。

而不是你担心如何测试内部实现细节。哪个-你没有;另一个答案完全正确!