What's a good way to unit test private methods that are not suitable to be retrieved as a new class?

Roughly speaking, I have a class that implements a thread with only one public method run

. This method goes into a loop, acting as a dispatcher to process network messages one by one; eg:

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
};

      

So the main thing is that I really don't want

  • Extract private methods from another class, because semantically they are part of it WorkerThread

    .
  • Make methods public, because they are not used outside the class.
  • Skip the tests, because these are the methods that implement the main logic.

But how can private methods be checked elegantly?

Note:

  • There should probably be multiple public methods to handle the start and end of a stream, but that's not a problem.
  • I think this problem is not limited to c++

    , so I marked it more popular statically typed Java

    to get more attention: P
+3


source to share


2 answers


Quoting the question:

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

And this is not true . You are violating the Single Responsibility Principle .

Providing "multithreading support" and "doing the actual work" are two different things. You must not ensure that "doing the actual work" is implementation-private information.

In this sense: the rules you set for yourself actually made you write a tough test . So, instead of "getting around" the symptoms of bad design, it's better to step back and fix your design.



In other words:

  • rework the workflow to be able to run any kind of work.
  • separate problems; and put "this kind of work" in a specialized class

By doing this, you will not only improve your design, but also make testing much easier: because now you can unit test "do the actual work" without any multi-threaded complexity. You are simply claiming that stuff works when done sequentially. Then you test the multithreaded part - yourself; without worrying about real work. And at the end of the day, everything fits together perfectly.

Instead of worrying about how to test internal implementation details. Which - you don't; the other answer here is completely correct!

+3


source


Simply put: Don't. Test the public interface and nothing else. Ultimately, this is the only thing that matters.



If you want to make sure that it is working correctly, the read / write functions should be accessed through IoInterface

which can be manufactured for testing.

+10


source







All Articles