I am working on a java project. I am new to unit testing. What is the best way to unit test private methods in java classes?
|
|
You generally don't unit test private methods directly. Since they are private, consider them an implementation detail. Nobody is ever going to call one of them and expect it to work a particular way. You should instead test your public interface. If the methods that call your private methods are working as you expect, you then assume by extension that your private methods are working correctly. |
|||||||||||||||||||||
|
|
In general, I would avoid it. If your private method is so complex that it needs a separate unit test, it often means that it deserved its own class. This may encourage you to write it in a way which is reusable. You should then test the new class and call the public interface of it in your old class. On the other hand, sometimes factoring out the implementation details into separate classes leads to classes with complex interfaces, lots of data passing between the old and new class, or to a design which may look good from the OOP point of view, but does not match the intuitions coming from the problem domain (e.g. splitting a pricing model into two pieces just to avoid testing private methods is not very intuitive and may lead to problems later on when maintaining/extending the code). You don't want to have "twin classes" which are always changed together. When faced with a choice between encapsulation and testability, I'd rather go for the second. It's more important to have the correct code (i.e. produce the correct output) than a nice OOP design which doesn't work correctly, because it wasn't tested adequately. In Java, you can simply give the method "default" access and put the unit test in the same package. Unit tests are simply part of the package you're developing, and it's OK to have a dependency between the tests and the code which is being tested. It means that when you change the implementation, you may need to change your tests, but that's OK -- each change of the implementation requires re-testing the code, and if the tests need to be modified to do that, then you just do it. In general, a class may be offering more than one interface. There is an interface for the users, and an interface for the maintainers. The second one can expose more to ensure that the code is adequately tested. It doesn't have to be a unit test on a private method -- it could be, for example, logging. Logging also "breaks encapsulation", but we still do it, because it's so useful. |
|||
|
First of all, as other authors suggested: think twice if you do really need to test private method. And if so, ... In .NET you can convert it into "Internal" method, and make package "InternalVisible" to your unit test project. In Java you can write tests itself in the class to be tested and your test methods should be able to call private methods as well. I don't really have big Java experience, so that's probably not the best practice. Thanks. |
||||
|
|
|
Testing of private methods would depend on their complexity; some one line private methods wouldn't really warrant the extra effort of testing (this can also be said of public methods), but some private methods can be just as complex as public methods, and difficult to test through the public interface. My preferred technique is to make the private method package private, which will allow access to a unit test in the same package but it will still be encapsulated from all other code. This will give the advantage of testing the private method logic directly instead of having to rely on a public method test to cover all parts of (possibly) complex logic. If this is paired with the @VisibleForTesting annotation in the Google Guava library, you are clearly marking this package private method as visible for testing only and as such, it shouldn't be called by any other classes. Opponents of this technique argue that this will break encapsulation and open private methods to code in the same package. While I agree that this breaks encapsulation and does open private code to other classes, I argue that testing complex logic is more important than strict encapsulation and not using package private methods which are clearly marked as visible for testing only must be the responsibility of the developers using and changing the code base. Private method before testing:
Package private method ready for testing:
Note: Putting tests in the same package is not equivalent to putting them in the same physical folder. Separating your main code and test code into separate physical folder structures is good practice in general but this technique will work as long as the classes are defined as in the same package. |
|||
|
|
|
If you really need to test private method, with Java I mean, you can use Import the library with maven (given versions are not the lastest I think) or import it directly in your classpath:
As an example, if you have a class named 'MyClass' with a private method named 'myPrivateMethod' which take a String as parameter an update its value to 'this is cool testing !', you can do the following junit test:
This library also enables you to replace any bean properties (no matter they are private and no setters are written) by a mock, and using this with Mockito or any other mock framework is really cool. The only thing you have to know at the moment (don't know if this will be better in next versions) is the name of the target field / method you want to manipulate, and its signature. |
|||||||
|
|
What I normally do in C# is make my methods protected and not private. It's a slightly less private access modifier, but it hides the method from all classes that do not inherit from the class under test.
Any class that doesn't inherit directly from classUnderTest has no idea that methodToTest even exists. In my test code, I can create a special testing class that extends and provides access to this method...
This class only exists in my testing project. Its sole purpose is to provide access to this single method. It allows me to access places that most other classes do not have. |
||||
|
|
|
You can test private methods easily if you put your unit tests in an inner class on the class you are testing. Using TestNG your unit tests must be public static inner classes annotated with @Test, like this:
Since it's an inner class, the private method can be called. My tests are run from maven and it automatically finds these test cases. If you just want to test one class you can do
Source: http://www.ninthavenue.com.au/how-to-unit-test-private-methods |
|||||||||
|
|
Dont use private methods. If you think about it for a while, you will realize that there is seldom need for private methods. At all. |
|||||||
|
