Reputation: 1627
I have an abstract class BaseTemplate
and multiple classes extending it. In one of the concrete class(SmsTemplate extends BaseTemplate
), we have a private variable Gson
. We have the same private variable(Gson
) in the abstract class as well.
While unit tesing the concrete class, methods in the abstract class is getting called from the concrete class. In my Unit test, I am using Whitebox.setInternalState(smsTemplateObj, gsonObj);
to inject the Gson object into the private members of SmsTemplate
and BaseTemplate
but the Gson is getting injected only in the subclass. In abstract class, its NULL
, meaning not injected. Below is the implementation.
Can someone please tell how to inject the Gson object in the abstract class?
abstract class BaseTemplate{
private Gson gson;//Here its not getting injected
protected String getContent(Content content){
return gson.toJson(content); // ERROR - gson here throws NPE as its not injected
}
}
class SmsTemplate extends BaseTemplate{
private Gson gson;//Here its getting injected
public String processTemplate(Content content){
String strContent = getContent(content);
...
...
gson.fromJson(strContent, Template.class);
}
}
Upvotes: 4
Views: 4257
Reputation: 8902
Whitebox.setInternalState()
method will only set the value of the first field it encounters going up through the hierarchy of the object you pass. So once it finds gson
field in your subclass, it won't look further and won't change the superclass field.
There are two solutions for this case:
Whitebox.setInternalState()
twice, one for each variable.Snippet:
Field field = smsTemplateObj.getClass().getSuperclass().getDeclaredField("gson");
field.setAccesible(true);
field.set(smsTemplateObj, gsonObj);
Upvotes: 7
Reputation: 852
You need a second abstraction layer:
abstract class BaseTemplate{
// private Gson gson;// no Gson here
protected String getContent(Content content){
// do what you want without Gson
}
}
abstract class BaseTemplateWithGson extends BaseTemplate{
protected Gson gson;
@Override
protected String getContent(Content content){
return gson.toJson(content);
}
}
class SmsTemplate extends BaseTemplateWithGson {
public String processTemplate(Content content){
String strContent = getContent(content);
...
...
gson.fromJson(strContent, Template.class);
}
}
Upvotes: 0