How to test private method java

How to test private method java

How to test private methods

To test a method you need to execute it, but calling private methods directly can be hard or even impossible, depending on the programming language you use. In this article I’ll primarily speak about Python and Java, but the described techniques surely can be applied to many other languages (but I can’t be sure about all of them).

What is a private method?

Have you ever asked yourself, why do you even need private methods? You need private data to maintain consistency, but why private methods?

Strictly speaking, you don’t. But they still be helpful at least for two major reasons:

While the first one prevents private data corruption, the second merely makes your API cleaner.

Don’t test it

Surprisingly, when I first came to Java programming and googled “How to test private method in Java”, the most popular answer was something like “Why do you want to test private methods? Users call public methods, test them instead”.

Well, that sounds crazy for me. I surely can just ignore the fact that a public methods call a private one, just imagine that private method code is inlined, but that means that code of the private method will be tested again and again with every public method that calls the private one.

In the following example you really want to test private method, not the two almost identical public ones.

One can notice that some refactoring can allow me not to test the private method. That’s true and we will talk about it later. But testing _set_status without any changes is still clean and reasonable way to do. I don’t buy this “don’t test private methods”.

Just call it

The simplest and most straightforward way to call a private method is, you know, call it. And that’s exactly what we do in Python and other languages that has private by convention (e. g. Perl).

To “just call it” in Java we need to change visibility of the method.

The first way is to make method package private (no access modifier) and put tests into the same package. This is a fairly common practice, but you still might want (or already have) another code structure.

The second way is to make method public. To let people know you still don’t want to call this method you can use @VisibleForTesting annotation from Guava or any other convention you like (that’s actually what Python and Perl do). By the way, IDEA totally understands that annotation and will warn you about using such public method outside of tests.

Nested class

You can also put a test class inside a tested one (at least in Java), but that doesn’t look great. You have to use the same file for both classes, and your production binaries will actually contain test code.

Reflection

In some languages reflections will do fine, in Ruby it’s that simple:

But in Java such code is so heavy I gave up on idea of providing an example here. More than this, you have to abandon all cool stuff your favourite IDE does for you.

Eliminate private

Personally I prefer the “just call it” method, and I like to use @VisibleForTesting in Java to make it happen.

But let us talk again about refactoring that allows me avoiding testing private methods (by eliminating them).

The point is to merge all private data and private methods into an object of another class that contains no private methods or data, but put the instance of that class into the only private attribute of the original class. Doesn’t sound simple, but it is, consider examples:

The described method can be useful not only for testing private methods, but also for more expressive design of your software. You can use any number of such private data classes so they have more sense semantically, not only technically.

For me, the most important thing about this pattern is that it proves that you technically can eliminate all private methods. But I still doubt that it’s reasonable to do it every time, your code can bloat without any significant benefit.

This article was written with the help of Nikolay Rys.

How to Unit test private methods in Java and Kotlin

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

Yes, This is a million-dollar question. How to unit test private methods?

Should a developer test the private methods in his codebase? or leaving them on the trust of public methods is a way. Every developer has its own opinion that whether should we actually test them or not. So, In a nutshell, the question got reduced to is “Is there exists any good approach we can try for this Job?”

So, here are all the possible options available to a developer to test private methods of his Java / kotlin based Apps in 2019:

D espite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection. It is not even that difficult. This can be very handy during unit testing.

Note: This only works when running the code as a standalone Java application, as you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager. But, since that is not something you need to do very often, it is left out of this text so far.

Method Parameter Reflection support was added in Java 8. Simply put, it provides support for getting the names of parameters at runtime.

Accessing Private Fields

To access a private field you will need to call the Class.getDeclaredField(String name) or Class.getDeclaredFields() method. The methods Class.getField(String name) and Class.getFields() methods only return public fields, so they won’t work. Here is a simple example of a class with a private field, and below that the code to access that field via Java Reflection:

Notice the line in bold too. By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can’t access the field using the normal code. The compiler won’t allow it.

Accessing Private Methods

To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method. The methods Class.getMethod(String name, Class[] parameterTypes) and Class.getMethods() methods only return public methods, so they won’t work.

Here is a simple example of a class with a private method, and below that the code to access that method via Java Reflection:

Notice the line in bold too. By calling Method.setAcessible(true) you turn off the access checks for this particular Method instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can’t access the method using the normal code. The compiler won’t allow it.

Let’s try this knowledge to some production-level code.
Here is the class containing some private methods which we want to test.

LoginPresenter.kt

Let’s test the private function saveAccount of loginPresenter

Junit test for private method

I read this question: How do I test a class that has private methods, fields or inner classes? and it seems that I might have a code smell, but my code is very simple to actually refactor. what is wrong in the design that I have created. I have created a delegate class for processing some actions it has three methods execute(Action); PopulateActionHandlers() and executeActionhandlers(); My class is like below:

Now I want to test populateActionHandlers() method with JUnit, which I made private as there is no need to expose it outside this class. If I test the execute() method then it will test both populateActionHandlers() and executeActionHandlers() methods which is testing two units at the same time, I want to test them separately. The design (I think) seems alright to me and doesnt allow any issues but then I would either change the access to the method (and only for the sake of testing it doesn’t justify that in my opinion, right?) or to use reflection (is that a good idea, it does not feel right somehow, do people usually use reflection for junit testing?). So the only thing that cant be ruled out is code smell. But may be my code sinus is not really helping me So I would like to understand if I can improve this code.

1 Answer 1

The recommendation not to test private methods should not prevent one to do a weird design by leaving out private method, but should enforce to test only methods that have clear semantics.

Private methods are usually technical helpers. Their semantics can change if the underlying data structures change, they can even be optimized away if the calling public methods use another algorithm to achieve the same goals.

I would rewrite the programm in following way:

Storing results of one function into a private field only to retrieve it from this field in another function is not threadsafe and harder to maintain.

Yet this refactoring would break all (yet not writte) tests that did test the private method of your example, because the interface is changed. If you had only tested the public method, the all tests would be valid after this refactoring.

I know few cases where testing private methods is ok. While testing private methods is often avoidable, I think the checking of private state is sometimes a better alternative than only checking the public state of objects. Such checks may be not as robust (reasons as above) but the public state is often incomplete and hard to assert. In both cases I use the framework picklock which enables one to access private methods and fields in a convenient way.

How do you unit test private methods?

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?

13 Answers 13

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.

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

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.

Testing Private method using mockito

How to test private method is called or not, and how to test private method using mockito?

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

13 Answers 13

Trending sort

Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.

It falls back to sorting by highest score if no posts are trending.

Switch to Trending sort

Not possible through mockito. From their wiki

Why Mockito doesn’t mock private methods?

Firstly, we are not dogmatic about mocking private methods. We just don’t care about private methods because from the standpoint of testing private methods don’t exist. Here are a couple of reasons Mockito doesn’t mock private methods:

It requires hacking of classloaders that is never bullet proof and it changes the api (you must use custom test runner, annotate the class, etc.).

It requires me to spend time implementing & maintaining it. And it does not make sense given point #2 and a fact that it is already implemented in different tool (powermock).

Finally. Mocking private methods is a hint that there is something wrong with OO understanding. In OO you want objects (or roles) to collaborate, not methods. Forget about pascal & procedural code. Think in objects.

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

You can’t do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here’s an example.

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

Here is a small example how to do it with powermock

To test method1 use code:

To set private object obj use this:

While Mockito doesn’t provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:

Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring.

How to test private method java. Смотреть фото How to test private method java. Смотреть картинку How to test private method java. Картинка про How to test private method java. Фото How to test private method java

By using reflection, private methods can be called from test classes. In this case,

**The approach is to combine reflection and spying the object. **method1 and **method2 are private methods and method1 calls method2.

Источники информации:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *