I want to set the value in the private field, but it doesn't work.

Asked 2 years ago, Updated 2 years ago, 148 views

There is a private field A that is not used by others.
However, I now need to access the field for testing.
To do this, we decided to access it using java.lang.reflect.

The field is in homegrown class B that you want to test and is a variable of type C.
Also,
to test self-made Class B due to program specifications You must create and set an instance of your own class C beforehand.

I used JUnit4 for the test. Within setUp, I have created and set an instance of self-class C.
However, during testing, class B says without an instance of class C.

So, I'm going to use a program that I just created to check. I tried setting and retrieving values to private fields.

SetCallTest class created for verification

package test;

import java.lang.reflect.Field;

public classSetCallTest{
    private HasPrivate hasPrivate;
    private Nakaminakami;

    public static void main(String[]args) {
        SetCallTest = newSetCallTest();
        System.out.println("Set Nakami".");
        test.setNakami();
        System.out.println("Retrieves the set Nakami.");
        test.getNakami();
        System.out.println("Retrieve the original Nakami.");
        test.getArimasu();
    }

    publicSetCallTest(){
        hasPrivate = new HasPrivate();
        Nakami=new Nakami();
    }

    public void setNakami(){
        try{
            Field privateField=HasPrivate.class.getDeclaredField("nakami");
            privateField.setAccessible(true);
            privateField.set(hasPrivate,nakami);
        } catch(NoSuchFieldException | SecurityException){
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch(IllegalArgumentExceptione){
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch(IllegalAccessExceptione){
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch(NullPointerExceptione){
            e.printStackTrace();
        }
    }

    public void getNakami(){
        try{
            Field privateField=HasPrivate.class.getDeclaredField("nakami");
            privateField.setAccessible(true);
            Nakaminakami2=(Nakami)privateField.get(hasPrivate);
            System.out.println("Retrieved Nakami:"+nakami2);
            System.out.println("Nakami:" + hasPrivate.getNakami());
            System.out.println("Nakami's nakami:"+nakami2.nakami);
        } catch(Exceptione){
            e.printStackTrace();
        }
    }

    public void getArimasu() {
        try{
            Field arimasu=HasPrivate.class.getDeclaredField("arimasu");
            arimasu.setAccessible(true);
            Nakaminakami2=(Nakami)arimasu.get(hasPrivate);
            System.out.println("Retrieved arimasu:"+nakami2);
            System.out.println("ariamsu:" + hasPrivate.getArimasu());
            System.out.println("arimasu no nakami:"+nakami2.nakami);
        } catch(Exceptione){
            e.printStackTrace();
        }
    }
}

HasPrivate Class Instead of Self-Created Class B

package test;

public class HasPrivate {
    private Nakaminakami;
    private Nakami arimasu=new Nakami();

    public Nakami getNakami(){
        return nakami;
    }

    public NakamigetArimasu(){
        return arimasu;
    }
}

Nakami class instead of self-made class C

package test;

public class Nakami {
    public String Nakami="Contents";
}

HasPrivate#arimasu can be retrieved from SetCallTest, but
HasPrivate#nakami is NullPointerException.

I was wondering if it wasn't set from SetCallTest HasPrivate has a public method for retrieving nakami and called it. It's the same.

Output Log

Set
Nakami.
Obtain the set Nakami.
Obtained nakami: test.Nakami@6d06d69c
Nakami:test.Nakami@6d06d69c received from HasPrivate
Nakami of Nakami: Contents
I will get the Nakami that I originally put in.
Retrieved arimasu: test.Nakami@7852e922
ariamsu:test.Nakami @7852e922 received from HasPrivate
nakami of arimasu: the contents

I'm sorry that I made too many mistakes in the confirmation code.
Here's an excerpt of the real code:

package com.example.sakaguchi.test.all.model;

import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.lang.reflect.Method;
import java.util.ArrayList;

import com.example.sakaguchi.model.PriceItem;
import com.example.sakaguchi.model.PriceListDataLoader;
import com.example.sakaguchi.model.PriceListData;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

/**
 * PhotoListData testing.
 * A dummy json is passed to test whether data can be acquired accordingly.
 * Currently, the following three patterns are available.
 * ·Group photo
 * ·Snap photographs, data sales available, development sales available
 * ·Session expired
 */
@LargeTest
@RunWith (AndroidJUnit4.class)
public class PriceListDataLoaderTest{
    PriceListDataLoader mPriceListDataLoader;
    PriceListDataPriceListData;
    JSONObject mPriceListJson, mSessionOutJson;

    @Before
    public void setUp(){
        mPriceListData=newPriceListDataLoader();

        mPriceListData = newPriceListData();
        Field priceListData=HasPrivate.class.getDeclaredField("mPriceListData");
    priceListData.setAccessible(true);
    priceListData.set(mPriceListDataLoader, mPriceListData);

        try{
            // Create json
        } catch(JSONExceptione){
            e.printStackTrace();
        }
    }

    /* The test method follows.
    * Invoke this private method of mPriceListDataLoader.
    * In the method, data obtained and processed from the argument json is put into PriceListData.
    * I would like to check the PriceListData to see if it contains the expected data.
    * However, it should have been set to mPriceListDataLoader in the first place.
    * mPriceListData is said to be null */
}

I can't try the real code because I don't have a production environment right now. It didn't work out
It is a confirmation program that I made to try without using JUnit4.
It was too appropriate and I made a lot of mistakes, but the code that I modified to work properly is
I don't think what I'm doing is that different, but
Is there something wrong with the real thing?

java junit

2022-09-30 20:57

3 Answers

setNakami, getNakami, and getArimasu methods respectively

HasPrivate hasPrivate=new HasPrivate();

There is a line called , but each of these hasPrivate is a different object.

setNakami(nakami);

When called, the HasPrivate object is created and the nakami is set to a private field, but the HasPrivate object with nakami setNakami in the private field is discarded and:

getNakami(nakami);

In the call to setNakami(nakami); re-created the HasPrivate object, which is different from the object you just set in the field, and the nakami field of the newly created HasPrivate object has just been created.

Nakaminakami2=(Nakami)privateField.get(hasPrivate);

nakami2 is null even if you read the fields as .

The reason is that the HasPrivate object is used in the setNakami, getNakami, and getArimasu methods, respectively, and the meaning of calling setNakami has disappeared.

Perhaps you would like to do something like this:
https://ideone.com/w3Xui9


2022-09-30 20:57

at the beginning of the method setNakami()
HasPrivate hasPrivate=new HasPrivate();

hasPrivate=newHasPrivate();

By doing so, the code you provided will work.

However, this code works even if you run Java without using JUnit4.
The assumption of using JUnit is to prepare and run classes for JUnit for the classes and methods that are running, and evaluate the results.

As for JUnit4, the following site is a simple sample code.
http://nanasess.net/mt/2008/04/junit4.html

This slide summarizes how to use JUnit 4 and what you can do.
http://www.slideshare.net/ichikaz3/junit4

Please refer to these as well.


2022-09-30 20:57

I checked the actual code today and found out that
The reason why it didn't work was because I made a mistake in the class when I reflected.
I'm sorry that I noticed the mistake if I had checked it properly.

package com.example.sakaguchi.test.all.model;

import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;

import com.example.sakaguchi.model.PriceItem;
import com.example.sakaguchi.model.PriceListData;
import com.example.sakaguchi.model.PriceListDataLoader;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

/**
 * PhotoListData testing.
 * A dummy json is passed to test whether data can be acquired accordingly.
 * Currently, the following three patterns are available.
 * ·Group photo
 * ·Snap photographs, data sales available, development sales available
 * ·Session expired
 */
@LargeTest
@RunWith (AndroidJUnit4.class)
public class PriceListDataLoaderTest{
    PriceListDataLoader mPriceListDataLoader;
    PriceListDataPriceListData;
    JSONObject mPriceListJson, mSessionOutJson;

    @Before
    public void setUp(){
        mPriceListDataLoader=newPriceListDataLoader();

        try{
            mPriceListData = newPriceListData();
            Field field=PriceListDataLoader.class.getDeclaredField("mPriceListData");
            // I accidentally wrote PriceListData instead of PriceListDataLoader.
            field.setAccessible(true);
            field.set (mPriceListDataLoader, mPriceListData);
        } catch(NoSuchFieldException){
            e.printStackTrace();
        } catch(IllegalAccessExceptione){
            e.printStackTrace();
        }

        try{
            // Create json
        } catch(JSONExceptione){
            e.printStackTrace();
        }
    }

    /* The test method follows.
    * Invoke this private method of mPriceListDataLoader.
    * In the method, data obtained and processed from the argument json is put into PriceListData.
    * Check the PriceListData to see if it contains the expected data.*/
}


2022-09-30 20:57

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.