Reputation: 8477
I have a generic class which maintains an internal array(say data) and number of elements(say N) in the array (both private).I can add elements to the array ,which will update the value of N.The public API of the class doesn't have get methods for the data array or N.Still I would like to write unit tests for checking the state of array and N.
public class InternalArray<T> {
private T[] data;
private int N;
private int head;
public InternalArray() {
super();
data = (T[]) new Object[10];
N = 0;
head = 0;
}
public void add(T item){
data[head]=item;
head++;
N++;
}
public T get(){
T item = data[--head];
N--;
return item;
}
}
Here, all I can test are the public APIs .. But I need to test the internal state of the private variables . I thought I would be able to access the fields using reflection.I tried the below code, I can get the value of N. When it comes to T[] data ,I can't figure out how to convert the resulting Object
to a String[]
( from call arrayf.get(inst)
)
public static void demoReflect(){
try {
Class t = Class.forName("InternalArray");
System.out.println("got class="+t.getName());
InternalArray<String> inst = (InternalArray<String>) t.newInstance();
System.out.println("got instance="+inst.toString());
inst.add("A");
inst.add("B");
Field arrayf = t.getDeclaredField("data");
arrayf.setAccessible(true);
Field nf = t.getDeclaredField("N");
nf.setAccessible(true);
System.out.println("got arrayfield="+arrayf.getName());
System.out.println("got int field="+nf.getName());
int nval = nf.getInt(inst);
System.out.println("value of N="+nval);
Object exp = arrayf.get(inst);
//how to convert this to String[] to compare if this is {"A","B"}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
This gave the output below
got class=InternalArray
got instance=InternalArray@c2ea3f
got arrayfield=data
got int field=N
value of N=2
Upvotes: 1
Views: 4550
Reputation: 726909
The Object
that you get from the call of arrayf.get(inst)
is of type Object[]
, not String[]
, because Java generics are implemented through type erasure. You can do this:
Object[] strings = (Object[])arrayf.get(inst);
System.out.println(strings.length);
for (int i = 0 ; i != strings.length ; i++) {
String s = (String)strings[i];
...
}
P.S. I am going to stay away from the discussion on whether it's a good idea to unit test the private details of the implementation.
Upvotes: 2