Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit-testing private methods: Facade pattern

Lots of developers think that testing private methods is a bad idea. However, all examples I've found were based on the idea that private methods are private because calling them could break internal object's state. But that's not only reason to hide methods.

Let's consider Facade pattern. My class users need the 2 public methods. They would be too large. In my example, they need to load some complex structure from the database's BLOB, parse it, fill some temporary COM objects, run user's macro to validate and modify these objects, and serialize modified objects to XML. Quite large functionality for the single metod :-) Most of these actions are required for both public methods. So, I've created about 10 private methods, and 2 public methods do call them. Actually, my private methods should not necessarily be private; they'll not break the internal state of instance. But, when I don't wont to test private methods, I have the following problems:

  1. Publishing them means complexity for users (they have a choice they don't need)
  2. I cannot imagine TDD style for such a large public methods, when you're to write 500+ lines of code just to return something (even not real result).
  3. Data for these methods is retrieved from database, and testing DB-related functionality is much more difficult.

When I'm testing private methods:

  1. I don't publish details that would confuse users. Public interface includes 2 methods.
  2. I can work in TDD style (write small methods step-by-step).
  3. I can cover most of class's functionality using test data, without database connection.

Could somebody describe, what am I doing wrong? What design should I use to obtain the same bonuses and do not test private methods?

UPDATE: It seems to me I've extracted everything I was able to another classes. So, I cannot imagine what could I extract additionally. Loading from database is performed by ORM layer, parsing stream, serializing to XML, running macro - everything is done by standalone classes. This class contains quite complex data structure, routines to search and conversion, and calls for all mentioned utilities. So, I don't think something else could be extracted; otherwise, its responsibility (knowledge about the data structure) would be divided between classes.

So, the best method to solve I see now is dividing into 2 objects (Facade itself and real object, with private methods become public) and move real object to somewhere nobody would try to find it. In my case (Delphi) it would be a standalone unit, in other languages it could be a separate name space. Other similar option is 2 interfaces, thanks for idea.

like image 971
Abelevich Avatar asked Jan 08 '09 20:01

Abelevich


People also ask

Can we test private methods in unit testing?

Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods aren't aware of. Furthermore, changing our implementation details shouldn't lead us to change our tests.

Can we test private methods in JUnit?

So whether you are using JUnit or SuiteRunner, you have the same four basic approaches to testing private methods: Don't test private methods. Give the methods package access. Use a nested test class.

When should I use facade pattern?

Developers often use the facade design pattern when a system is very complex or difficult to understand because the system has many interdependent classes or because its source code is unavailable. This pattern hides the complexities of the larger system and provides a simpler interface to the client.

What is a Facade in a unit?

Façade systems comprise the structural elements that provide lateral and vertical resistance to wind and other actions, and the building envelope elements that provide the weather resistance and thermal, acoustic and fire resisting properties.


2 Answers

I think you are putting too many responsibilities (implementations) into the facade. I would normally consider this to be a front-end for actual implementations that are in other classes.

So the private methods in your facade are likely to be public methods in one or more other classes. Then you can test them there.

like image 58
krosenvold Avatar answered Sep 20 '22 05:09

krosenvold


Could somebody describe, what am I doing wrong?

Maybe nothing?

If I want to test a method I make it default (package) scope and test it.

You already mentioned another good solution: create an interface with your two methods. You clients access those two methods and the visibility of the other methods don't matter.

like image 20
Jeffrey Fredrick Avatar answered Sep 19 '22 05:09

Jeffrey Fredrick