【问题标题】:How to inject the variable in the abstract class while unit testing the subclass?如何在对子类进行单元测试时在抽象类中注入变量?
【发布时间】:2015-08-05 11:27:16
【问题描述】:

我有一个抽象类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);
    }
}

【问题讨论】:

  • 使抽象类的字段受保护,并从子类中删除删除字段。
  • @Stefan - 啊……问题是,Gson 对象并未在所有具体类中使用。
  • 为什么在抽象类和子类中需要一个gson变量?
  • @bryce - 在抽象类和子类中(不是在所有子类中),显然都需要 gson 对象。
  • 如果不是所有具体类都需要 Gson 对象,则需要第二层抽象。没有 Gson 的 BaseTemplate 是一个扩展 BaseTemplate 的抽象类,在这个类中是 Gson 对象。不需要 Gson 对象的具体类扩展 BaseTemplate 和其他扩展你的第二个抽象类

标签: java unit-testing junit mockito


【解决方案1】:

Whitebox.setInternalState() 方法只会设置它遇到的第一个字段的值,它会向上穿过您传递的对象的层次结构。因此,一旦它在您的子类中找到 gson 字段,它就不会进一步查找,也不会更改超类字段。

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

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

片段:

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

【讨论】:

    【解决方案2】:

    您需要第二个抽象层:

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

    【讨论】:

    • 我喜欢第二层抽象。有没有其他没有第二抽象的单元测试方法?
    • 对我来说,不是单元测试的问题,而是设计的问题……当难以对某些东西进行单元测试时,请提出设计问题;-)
    • 您能说说实现中的设计问题吗?
    • 问题是如果某些子类不需要的话,父抽象类中要有一个属性Gson...
    • 父类中的属性只有私有属性,不需要的子类无法访问。
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2019-11-25
    • 2014-10-08
    • 2011-03-24
    • 2022-10-02
    相关资源
    最近更新 更多