[JAVA] How to test private scope with JUnit

Test what is private scope

In Java, call private scope fields, methods, inner classes from the outside, Let's test it with JUnit.

First, let's try testing with JUnit.

error.png

There is a compilation error. It is a specification. Cannot be executed. Since it is private, it cannot be called in the same way as public.

So we use Reflection to call something private scope.

What is Reflection?

Reflection is a type of Java standard library. It is dealing with information about the class itself. As a concrete example With a string of class name, method name, field name Generate that class, execute methods, access fields I can do it.

The following is an external site, but it looks like this, for example. http://java.keicode.com/lang/reflection.php

"If it's so convenient, use it positively." You may think that. However, Reflection is a double-edged sword. Be careful when handling. ** But I will introduce it. ** **

Problems with Reflection

Reflection depends on how you use it

--Class design collapses --Code is hard to write and hard to read --Performance is worse than calling a method normally

There are also problems such as. ** But I will introduce it. ** **

"Test private scope with JUnit" This is because it is used for a limited purpose.

Return to the main subject

Let's fix the JUnit test class, which is full of errors.

package jp.co.illmatics.sample;
/**
 *Class to be tested
 */
@SuppressWarnings("unused")
public class PrivateSample {

    private String field = "Hello field!";

    private final String finalField = "Hello final field!";

    private String doIt()    {
        return "Hello method!";
    }

    private class InnerClass {
        public InnerClass() {

        }
        public String getInnerMethod() {
            return "Hello inner method!";
        }
    }
}
package jp.co.illmatics.sample;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Test;

import junit.framework.TestCase;

/**
 *Test class
 */
public class PrivateSampleTest extends TestCase {

    PrivateSample privateSample = new PrivateSample();
    String expected = "";
    String actual = "";

    @Test
    public void testField() throws Exception {
        final String fieldName = "field";
        expected = "Hello field!";
        actual = (String) getFieldValue(privateSample, fieldName);
        assertEquals(expected, actual);
    }

    @Test
    public void testFinalField() throws Exception {
        final String finalFieldName = "finalField";
        expected = "Hello updated final Field!";
        actual = (String) getUpdatedFinalFieldValue(privateSample, expected, finalFieldName);
        assertEquals(expected, actual);
    }

    @Test
    public void testMethod() throws Exception {
        final String methodName = "doIt";
        expected = "Hello method!";
        actual = (String) getMethodValue(privateSample, methodName);
        assertEquals(expected, actual);
    }

    @Test
    public void testInnerClassMethod() throws Exception {
        final String innerClassName = "jp.co.illmatics.sample.PrivateSample$InnerClass";
        final String innerMethodName = "getInnerMethod";
        expected = "Hello inner method!";
        actual = (String) getInnerClassMethod(privateSample, innerClassName, innerMethodName);
        assertEquals(expected, actual);
    }

    private Object getFieldValue(PrivateSample privateSample, String fieldName)
            throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
            SecurityException {
        return getPrivateField(privateSample, fieldName).get(privateSample);
    }

    private Field getPrivateField(PrivateSample privateSample, String fieldName)
            throws NoSuchFieldException, SecurityException, IllegalArgumentException,
            IllegalAccessException {
        Class<?> clazz = privateSample.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field;
    }

    private Object getUpdatedFinalFieldValue(PrivateSample privateSample, String newValue,
            String fieldName) throws NoSuchFieldException, SecurityException,
                    IllegalArgumentException, IllegalAccessException {
        Field finalField = getPrivateField(privateSample, fieldName);
        finalField.set(privateSample, newValue);
        return finalField.get(privateSample);
    }

    private Object getMethodValue(PrivateSample privateSample, String name)
            throws NoSuchMethodException, SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        Method doIt = PrivateSample.class.getDeclaredMethod(name);
        doIt.setAccessible(true);
        return doIt.invoke(privateSample);
    }

    private Object getInnerClassMethod(PrivateSample parent, String classFullName,
            String methodName) throws ClassNotFoundException, NoSuchMethodException,
                    SecurityException, InstantiationException, IllegalAccessException,
                    IllegalArgumentException, InvocationTargetException {
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        Class<?> innerClazz = loader.loadClass(classFullName);
        Constructor<?> constructor = innerClazz.getDeclaredConstructor(parent.getClass());
        constructor.setAccessible(true);
        Object innerObj = constructor.newInstance(parent);
        return innerClazz.getDeclaredMethod(methodName).invoke(innerObj);
    }
}

resolved.png I was able to fix it.

testStart.png Test

testSucceeded.png It's done.

Recommended Posts

How to test private scope with JUnit
[Java] How to test for null with JUnit
How to test interrupts during Thread.sleep with JUnit
How to test private methods with arrays or variadic arguments in JUnit
[Java] Test private methods with JUnit
How to test a private method with RSpec for yourself
How to filter JUnit Test in Gradle
How to use JUnit 5
Unit test with Junit.
JUnit 5: How to write test cases in enum
How to write test code with Basic authentication
Test Web API with junit
How to unit test with JVM with source using RxAndroid
How to use JUnit (beginner)
How to number (number) with html.erb
How to update with activerecord-import
How to perform UT with Excel as test data with Spring Boot + JUnit5 + DBUnit
Test private methods in JUnit
How to write Junit 5 organized
How to migrate from JUnit4 to JUnit5
[Creating] How to use JUnit
[Rails] How to use Scope
How to run only specific files with gem's rake test
How to erase test image after running Rspec test with CarrierWave
[Java] I want to test standard input & standard output with JUnit
How to scroll horizontally with ScrollView
How to use scope (JSP & Servlet)
How to unit test Spring AOP
How to get started with slim
How to enclose any character with "~"
How to use mssql-tools with alpine
How to get along with Rails
[RSpec] How to write test code
Test Spring framework controller with Junit
How to start Camunda with Docker
How to crop an image with libGDX
How to adjustTextPosition with iOS Keyboard Extension
How to share files with Docker Toolbox
How to compile Java with VsCode & Ant
[Java] How to compare with equals method
[Android] How to deal with dark themes
How to use BootStrap with Play Framework
[Rails] How to use rails console with docker
How to switch thumbnail images with JavaScript
[Note] How to get started with Rspec
How to do API-based control with cancancan
How to fix system date in JUnit
How to achieve file download with Feign
How to update related models with accepts_nested_attributes_for
How to set JAVA_HOME with Maven appassembler-maven-plugin
How to handle sign-in errors with devise
How to delete data with foreign key
JUnit 5 gradle test fails with lombok annotation
How to monitor nginx with docker-compose with datadog
Java automated test implementation with JUnit 5 + Gradle
How to deal with Precompiling assets failed.
How to write an RSpec controller test
[SpringBoot] How to write a controller test
How to achieve file upload with Feign
How to run Blazor (C #) with Docker
How to build Rails 6 environment with Docker