3

Let's suppose there is an utility class (no data) with one complex (as in, hard-to-test) public method. It uses random number generation, return large arrays of data and that fun stuff. However, if you implement it in small private methods, every private method would be easy to test, and thus the whole thing would be easier to test. From the application point of view, only the big method needs to be public, and the other should be private. Yet, testing the private methods results in an easier to test class. How should I approach this problem?

4

5 回答 5

5

Sometimes generating random numbers, returning large arrays and other fun stuff means that the single utility class is responsible for more than one thing which means there should be more classes instead. High complexity in a single class (single method!) is sometimes the sign of bad design. But there's never one single golden rule to follow.

于 2012-10-15T00:00:59.167 回答
1

The need to test private methods should be a warning sign. It is not the solution to your big and complex method. Extraction of functionality into smaller classes IS the solution, concidering the Single Responsibility Principle (SRP). SRP states that a class should really only do one thing.

Random number generation, array handling and fun stuff is at least three separate things, that should be done separately.

于 2012-10-15T07:24:43.287 回答
1

Whether you should leave your method as a single blackbox algorithm whose subparts aren't testable, or try to externalize as many responsibilities as possible to separate classes, is very situational.

You might have subparts that are likely to be reused, in which case it's a good idea to factor them out. You might have subparts that talk to other layers or to the hardware - same thing.

It all depends on what these small sub methods do, it's hard to tell without a context.

于 2012-10-15T14:12:51.737 回答
0

There's a very strong argument for only testing the public API of a class. It makes refactoring your code that much easier because unless you change the method signature, the unit tests won't need to change and they'll validate that your changes didn't break anything.

That being said sometimes it can make sense to test the private methods (although this would be the exception - not the rule). Some test frameworks (e.g. MSTest) let you access private members for just this purpose while others (e.g. nUnit) don't since they don't think you should be doing it (in the case of .Net it doesn't take too much to write your own reflection class/method to give you access though).

If you do decide to test your private methods, make sure you also test the full public method too as you'll need the public tests to verify your later refactors, as mentioned above.

于 2012-10-15T00:49:21.767 回答
0

Testing private members will always make your tests brittle. When you test private methods, your tests are dependent on implementation details that can and will often change. The reason you made them private to begin with, is that you want to be able to change them without impacting the rest of your software. Guess what: if you expose your privates, even if it is only using reflection "black magic", you are making them public, because your tests are part of your software as well.

If you feel that you must test the implementation details, whether because your public API does too much, or because the private methods are so important, you should refactor your code and extract your private members as public classes and test those. Remember, because your tests are also part of the software, they should have "normal" access to the code that they use.

If you are adamant that these (not so) private methods cannot be publicly exposed, perhaps for fear of allowing external users / code to access them, you can limit the access to these classes by making them internal (in C#) or package-private (in Java), and have the code's internals visible to your tests.

Either way, it sounds that your code should either not be tested or should be made (more) public.

于 2012-10-16T08:25:09.840 回答