4

I want to test a private method in a final utitlity class.

1. The class itself:

The class signature is:

public final class SomeHelper {

    /** Preventing class from being instantiated */
    private SomeHelper() {
    }

And there is the private method itself:

private static String formatValue(BigDecimal value)

The test is allready written, but earlier, the method was in a non-utility non-final class without a private constructor.

The test is using @RunWith(Parameterized.class) already.

Now all I get is an exception:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class com.some.package.util.SomeHelper
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

2. The test

The most important line in this test is:

String result = Whitebox.invokeMethod(mValue, "formatValue", mGiven);

Is there a way of making the test work?

hc0re
  • 1,806
  • 2
  • 26
  • 61
  • Why are you trying to create a mock **instance** of a class in order to test one of its **static** methods? – JB Nizet Feb 17 '16 at 09:29
  • Reflection can be used to invoke private method. Please see this - http://stackoverflow.com/questions/34571/how-to-test-a-class-that-has-private-methods-fields-or-inner-classes ? – Sachin Feb 17 '16 at 09:30
  • 1
    Ideally you should not test private methods. Test the public methods calling this private method as it is one unit in itself. – bluelurker Feb 17 '16 at 09:31
  • May be **PowerMock** can help you – mmuzahid Feb 17 '16 at 09:37

3 Answers3

8

You don't need to test private methods.

But you SHOULD test the ones that use it. If methods that call your private methods are working as you expect, you can assume private methods are working correctly.

Why?

Nobody will call this method alone, so unit test for it is unnecessary.

Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
1

You don't need to test private method, because it'll not be called directly. But if it realizes some so complicated logic, you want to do this, you should consider extracting class.

Piotr Bujok
  • 103
  • 9
0

What I finally did is based on the answer from question How do I test a class that has private methods, fields or inner classes? that @Sachin Handiekar provided in a comment.

It's not the most beautiful way, considering that private methods should not be tested, but I wanted it tested and I was just curious.

This is how I did it.

Class someHelper = SomeHelper.class;
Method formatValue = someHelper.getDeclaredMethod("formatValue ", BigDecimal.class);
formatValue.setAccessible(true);
String result = (String) formatValue .invoke(new String(), mGiven);

And it works like a charm.

Community
  • 1
  • 1
hc0re
  • 1,806
  • 2
  • 26
  • 61
  • 1
    The fact that something works does not make it a good idea ;-) You can even set final variables via reflection, so the bar for "it works" is pretty low... – Florian Schaetz Feb 17 '16 at 11:25
  • Actually your sollution is a good excercise, but not the best practice as @Florian said. Also, if you cannot test private method in another way than this, **just delete it** because is useless. – Jordi Castilla Feb 17 '16 at 12:17
  • @JordiCastilla How do I test a private method that handles an exception, when that exception is thrown by final classes (which Mockito isn't able to mock/spy)? – Vivek Chavda Jan 27 '17 at 22:22
  • @vivek just test the class that calls private method and handle exception with try catch and fails or accep it if valid – Jordi Castilla Jan 27 '17 at 22:59