Junit Test Case for private method

We Are Going To Discuss About Junit Test Case for private method. So lets Start this Java Article.

Junit Test Case for private method

  1. Junit Test Case for private method

    Why is loading_status static? Basically 2 instances of this class would use the same loading_status variable. loading_status should either not be static or checkLoadingStatus should be static as well.

  2. Junit Test Case for private method

    Why is loading_status static? Basically 2 instances of this class would use the same loading_status variable. loading_status should either not be static or checkLoadingStatus should be static as well.

Solution 1

First of all a couple of things:

  1. Why is loading_status static? Basically 2 instances of this class would use the same loading_status variable. loading_status should either not be static or checkLoadingStatus should be static as well.
  2. loading_status is terribly named. If you want to keep it static, you should name it LOADING_STATUS. If it won’t be static, let’s name it loadingStatus. That’s the Java convention.
  3. You should create a proper enum type for loading_status instead of it being an integer.
  4. while (loading_status == IN_PROGRESS); is just simply bad practice. At least what you can do is: while(loading_status == IN_PROGRESS) { Thread.sleep(100); }; However a timeout is a better practice. Sometehing like:
long timeoutMillis = 5000L; // Should come from a configuration or something
long endTimeMillis = System.currentTimeMillis() + timeoutMillis;
while (loadingStatus == IN_PROGRESS) {
    long remainingMillis = end - System.currentTimeMillis();
    if (remaining <= 0) {
        // Timeout while loading
        loadingStatus = LOADING_ERROR;
        break;
    }
    Thread.sleep(50);
}
// ...

And finally I guess something will update loadingStatus to completed or something.
I guess you are using synchronized there as well.
If the loading happends on 2 different threads then you will end-up in a dead-lock.
If checkLoadingStatus enter the synchronized block first, so when the loading is completed the loading thread will never be able to enter the synchronized block, because the checkLoadingStatus is holidng the lock.

Last but not least to answer you question, if you want to keep your method private, you can invoke it through reflection, but that’s again bad practice.
Generally you should avoid unit testing private methods and unit test those methods which are invoking it.
If however you definitely need to unit test a particular method, make it package-private instead of private, and then you can create a unit test in the same package where the class is which contains your method. And you can add a comment to the method saying it’s only visible for unit testing. Example of your code structure in this case:

src
+-- main
+-- +-- com/app/MyClass.java
+-- test
    +-- com/app/MyClassTest.java // this test class will able to access package-private methods in MyClass

Original Author Of This Content

Solution 2

Normally, when you are not able to test your code, you should think of rewriting it, so that it is testable. Private methods cannot be called in a regular way, outside of your class, not even within a JUnit test.

There are a few things you could do to make it testable:

  1. Rewrite your code to split the method into smaller ones. Should always be done, where appropriate.

  2. You could make the method package private (remove the private modifier), so your test class, which has to be in the same package, can access it.

  3. You could make the method protected, so you could inherit your class in your test and indirectly call that method over your inherited class.

  4. You could call a method, that calls the method, you want to test and make your assertions accordingly.

If you tend to change the method’s visibility to package private or protected, you could annotate your method as @VisibleForTesting, so tools like Sonar and other team members know, why it is not private.

Hope it helps.

Original Author Of This Content

Solution 3

Your private method works according to the internal private variable loading_status value so on your tests you should just be able to change that variable.
To do this you can do as follow:

package com.test

import com.test.SchemaMaintenance;
import org.junit.Test;
import org.mockito.internal.util.reflection.Whitebox;

public class SchemaMaintenanceTest {

    @Test
    public void TestSchema() throws Exception {
        SchemaMaintenance schema = new SchemaMaintenance();
        Whitebox.setInternalState(schema,"loading_status",2);
        schema.startSchemaMaintenance();
    }

}

Supposing You should include the mockito dependency on your project:

e.g. Maven

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>1.6.4</version>
</dependency>

Original Author Of This Content

Solution 4

Here’s an approach that worked for me.

  1. Make a public “tester” inner class in your class.
    • If you are testing an inner class the “tester” still needs to be on the outer class.
  2. The tester is a delegate for the private methods you’d like to test.
  3. Add a method to your class to get and instance of the tester
  4. In your test method get an instance of the tester and
  5. Invoke your private method via the appropriate tester instance method.

There will be different variations depending on the access to methods and inner classes, etc required.

This example can’t have a static “tester” because we needed to test methods in a non-static inner class.

//  Outer owner class
//
public class OwnerClass Class {
    
    private class InnerClass {
            : 
            
        //  method I'm testing
        //
        private void doSomething)( String name ){
            ...
        }
    }
    
        :
    
    //  Tester class
    //
    public class InnerClassTester {
        
        private final InnerClass        innerClass    = new InnerClass();
            :
            
        //  test invocatiion
        //
        private void doSomething)( String name ){
            
            innerClass.doSomething)( name )
        }
    }

    //  Get an instance of the tester
    //    
    public InnerClassTester getInnerClassTester() {
        return new InnerClassTester();
    }

Inside your the Unit Test …

@Test
public void doSomethingTest() throws Exception {
    
    OwnerClass ownerClass = new OwnerClass();
    innerClassTester      = ownerClass.InnerClassTester();
            :
            
    //  Test the private method
    //
    innerClassTester.doSomething( "123456" );
}

Works with debugger. You need to be flexible defining the tester and the tester-getter depending on your access. The tester can probably be protected too, I didn’t try that. All the best.

Original Author Of This Content

Conclusion

So This is all About This Tutorial. Hope This Tutorial Helped You. Thank You.

Also Read,

Siddharth

I am an Information Technology Engineer. I have Completed my MCA And I have 4 Year Plus Experience, I am a web developer with knowledge of multiple back-end platforms Like PHP, Node.js, Python and frontend JavaScript frameworks Like Angular, React, and Vue.

Leave a Comment