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

C++ 对不适合提取为新类的私有方法进行单元测试的好方法是什么?,c++,unit-testing,design-patterns,tdd,C++,Unit Testing,Design Patterns,Tdd,粗略地说,我有一个类,它只使用一个公共方法run实现一个线程。该方法进入一个循环,就像调度器一样逐个处理网络消息;例如: class WorkerThread { public: void run() { while (!b_shutdown) { message = getNextMessage(); switch(message.type) { case WRITE: write();

粗略地说,我有一个类,它只使用一个公共方法
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
};
所以主要的一点是我真的不想

  • 将私有方法提取到另一个类中,因为在语义上它们是此
    WorkerThread
    的一部分
  • 公开这些方法,因为它们不会在类之外的任何地方使用
  • 跳过测试,因为正是这些方法实现了主逻辑
  • 但是如何才能优雅地测试私有方法呢

    注:

  • 可能需要更多的公共方法来处理线程的启动和终止,但这不是这里要考虑的问题
  • 我认为这个问题并不局限于
    c++
    ,所以我用更流行的静态类型
    Java
    来标记它,以引起更多的注意:P

  • 简单地说:不要。针对公共接口进行测试,而不是其他。最终,这是唯一重要的事情

    如果您想查看它是否正常工作,则应通过可模拟测试的
    IoInterface
    访问读/写功能。

    引用问题:

    我真的不想将私有方法提取到另一个类,因为从语义上讲,它们是这个WorkerThread的一部分

    这是错误的。你违反了法律

    提供“多线程支持”和“做实际工作”是两件不同的事情。您应该而不是强制执行“实际工作”是一个私有的实现细节

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

    换言之:


    • 返工您的工作线程,以便能够运行任何类型的工作
    • 单独关注;把"这类工作"纳入专门课
    通过这样做,不仅可以改进设计,还可以使测试更加容易:因为现在,您可以对“实际工作”进行单元测试,而无需任何多线程复杂性。您只需断言,当按顺序完成时,这些内容是有效的。然后,您测试多线程部件—自行测试;不用担心实际工作。最后,一切都很好地结合在一起


    而不用担心如何测试内部实现细节。你不知道;另一个答案完全正确

    在构建单元测试时,您可以让部分单元测试框架成为待测试类的朋友。“因此,我也用更流行的静态类型Java对其进行了标记,以获得更多关注”,并且通常会得到更多的反对票。“因为从语义上讲,它们是这个WorkerThread的一部分”,我似乎不这么认为,WorkRead似乎只是一个消息分派器。@ RICHARDCRITITY是的,但是我想问一个关于软件设计的一般问题,而不是使用TDD的C++特定的问题,它消除了这个问题,因为它阻止了编写无法测试的私有方法。最终,您可以通过调用它们的公共接口来测试它们。使用TDD,您很可能会在编写测试后重构公共接口,将代码移动到prove方法中。这有一定意义,但有点表明,在OOP中,所有私有方法都可以提取为另一个(比如
    IoInterface
    )类的公共方法,并通过该类的私有实例进行访问。这是一种合理的风格吗?很好的简短/准确的回答。你遗漏了一些细节,让我写下另一个答案;谢谢你;-)@wlnirvana:每个职业都应该有一个改变的理由或一个责任。WorkerThread似乎负责多线程,而不应该负责读/写东西。有关详细信息,请参阅GhostCat的伟大答案。“能够运行任何类型工作的工作线程”真的启发了我。顺便问一下,我想问一下,哪一种设计通常被认为是更好的设计,以及为什么-拥有
    IoInterface的私有实例
    ,或者从工作线程和
    IoInterface
    进行多重继承?这一部分可能“过于固执己见”。我的观点:我更喜欢构图而不是继承。。。继承总是导致非常紧密的耦合;因此,就我个人而言,我试图避免它。您不是为了保存编码工作而继承的;但是因为有些类A实际上是B。意思是:OO是关于“A是-A是B”。。。因为你的模型告诉你这是正确的。