单元测试子类时如何在抽象类中注入变量?

时间:2015-08-05 11:27:16

标签: java unit-testing junit mockito

我有一个抽象类BaseTemplate和多个扩展它的类。在其中一个具体类(SmsTemplate extends BaseTemplate)中,我们有一个私有变量Gson。我们在抽象类中也有相同的私有变量(Gson)。

在测试具体类的单元时,抽象类中的方法是从具体类调用的。在我的单元测试中,我使用Whitebox.setInternalState(smsTemplateObj, gsonObj);将Gson对象注入SmsTemplateBaseTemplate的私有成员,但Gson仅在子类中注入。在抽象类中,它的NULL,意思是不注入。以下是实施。

有人可以告诉我们如何在抽象类中注入Gson对象吗?

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);
    }
}

2 个答案:

答案 0 :(得分:5)

Whitebox.setInternalState()方法只会设置它遇到的第一个字段的值,它通过您传递的对象的层次结构。因此,一旦它在您的子类中找到gson字段,它就不会再看起来并且不会更改超类字段。

这种情况有两种解决方案:

  • 更改变量名称。如果变量名称不同,您只需调用Whitebox.setInternalState()两次,每个变量一个。
  • 使用反射手动设置字段。您也可以使用以下代码段设置没有Mockito帮助的字段。

段:

Field field = smsTemplateObj.getClass().getSuperclass().getDeclaredField("gson");
field.setAccesible(true);
field.set(smsTemplateObj, gsonObj);

答案 1 :(得分:0)

您需要第二个抽象层:

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);
    }
}