Freewind
Freewind

Reputation: 198238

Is it OK to make a private method to non-private just because to make it easier for testing?

We are maintaining some legacy code and we are adding tests for them.

In order to write tests easier, we will extract some code into methods(which will be private be default), then writing tests for them. Since they are private, it's hard to invoke them, so what we did is: remove the "private" keyword, make it "non-private", then write tests.

But it makes some methods non-private which are supposed to be "private". Is it OK to do this, or is there any better solutions?


Update:

I think I'd better to provide some more background:

The code is very complicated and not good, and has nearly no tests. Writing tests for public methods are not possible since they have lots of hard-coded external dependencies and which are not be mocked.

We need to fix some bugs, but without tests we can't do it. So we first extract some related code to some methods, add tests for them, then fix bugs.

Since the extracted methods are private by default, we have to make them non-private, otherwise we have to invoke them by reflection:

Method method = Somecls.class.getMethod("a-private-method");
method.setAccessible(true);
method.invoke(...)

But if we make it non-private, we can just:

Somecls cls = new Somecls();
cls.nonPrivateMethod(...)

Upvotes: 2

Views: 346

Answers (3)

diegomtassis
diegomtassis

Reputation: 3657

I think this is something pretty personal. In most of the scenarios I don't see any harm on changing the scope of a method from private to protected/package private if this helps to write better unit tests. It not only allows to invoke the method from your test - which you might do either way using reflection -, but also to override/mock that method when testing another one invoking this.

However, if you don't want to do it you still can use tools like Spring's ReflectionTestUtils to make the invocation of private methods less painful.

Upvotes: 1

Hiro2k
Hiro2k

Reputation: 5587

Yes this is perfectly acceptable for creating unit tests for the private methods. By leaving out the private keyword you create what is a known as a package-private method which can only be accesed by other classes that are in the same package. This lets you create unit test classes in the same package that can call your methods but also provides encapsulation so clients that use your class can't call those methods.

Upvotes: 0

Karthik
Karthik

Reputation: 1023

If the method is private, then it will be invoked by a public method in that class. Ideally, the test cases should pass through the public method to reach all the possible flows in that private method.

Upvotes: 3

Related Questions