Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing: private methods and how to refactor

I like unit testing, it is proving its worth immensely for the last year and a half or so ive used it. However I always have a problem or rather a niggle with private methods (and protected).

I don't want to make them public or use internals visible to attribute. I want a clean and crisp solution - that is testable and i'd be proud to let someone else look at.

I am coming to the conclusion that if a private method really needs testing independantly then maybe it should be moved out onto another interface and use association to expose the functionality to the calling method. I believe this in essence to be the Facade pattern.

Is this really the best way to go about this? Or more objectively ... are there any other approaches I have totally overlooked?

Edit: Are we talking about a specific language? I am working in C#. I had kept code out of the question as i was looking for something abstract. Coming back to it today i realise that is perhaps folly due to languages really being that different.

So some code:

public class CopmlexClass
{
    public void SomeMethod()
    { }

    private void workerMethod()
    { }
}

would get re factored into

public class CopmlexClass
{
    public void SomeMethod()
    { }

    public IComplexClassWorker Worker { get; set; }

}

public interface IComplexClassWorker
{
    void WorkerMethod();        
}

In fact id probably prefer to use constructor injection and not even expose the property

My question is: is that the best way? what are the alternatives bar reflection / internals visible to attribute?

like image 313
John Nicholas Avatar asked Dec 11 '25 21:12

John Nicholas


1 Answers

A private method which needs to be tested independently can be the result of the following:

  • your class is doing too much - its public methods implement functionality which is too complex to be unit tested as a whole, and/or
  • the effects of calling the specific private method can't be directly sensed from outside the class.

Both cases are usually a clear call to extract another class containing some private method(s) of the original class, turned into public, thus made directly testable. (The sometimes challenging part is to find logically cohesive chunks of functionality which can form useful classes on their own right. You may not always get a perfect result at first - in refactoring, sometimes one needs to make a compromise, a small step into some not-yet-clearly-defined direction. In the long term, such a step may open up new possibilities, call attention to other similar code parts, or the new class may start to attract code bits from other places, eventually forming a coherent class. Or turning into something completely new, but better than what you originally envisioned.)

Exposing the private method via another interface / facade is IMO not going to solve the problem in the long term, only muddles the waters. Classes should have a well defined, complete and minimal interface. Exposing private methods in any way may open up ways to compromise the internal state of the object, which is a Bad Thing.

like image 149
Péter Török Avatar answered Dec 14 '25 12:12

Péter Török



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!