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 typedJava
to get more attention: P
source to share
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!
source to share