繁体   English   中英

创建某种工厂时应避免使用静态方法进行可测试性

[英]Avoiding Static method for testability when creating a sort of Factory

重构某些代码时,我发现有一个new调用创建了一个具体的类。

我一直在寻找一种避免调用创建具体类并提高可测试性的方法,因此我创建了一种Factory,负责为我返回一个实例。 然后,我使用Spring构造函数注入将工厂注入被测系统。

但是,现在我面临着一个问题,那就是在我的工厂中使该方法静态化,同时又具有良好的可测试性。 根据Misko Hevery的说法, 静态方法将导致可测试性的死亡,但是我不清楚如何删除对new的调用,具有良好的单元测试以及避免静态方法的调用。

这是使用工厂的类的摘录。 我正在测试此类中的方法,这些方法利用了已构造的(和模拟的)columnFamilyTemplate:

protected AlertFieldMatcher(ColumnFamilyTemplateBuilder columnFamilyTemplateBuilder, Keyspace keyspace,
                            T2JsonUtilInterface jsonUtil) {
    this.columnFamilyTemplate = columnFamilyTemplateBuilder.build(keyspace, CF_ALERT);
    this.jsonUtil = jsonUtil;
}



这是工厂,现在我必须在测试中模拟SUT中的方法(如上所述):

public class DefaultColumnFamilyTemplateBuilder 
                                         implements ColumnFamilyTemplateBuilder {


   @Override
   public ColumnFamilyTemplate<String, String> build(Keyspace keyspace, 
                                                       String columnFamily) {
       ColumnFamilyTemplate<String, String> builtTemplate = 
                                                 new ThriftColumnFamilyTemplate<String, String>
                                                    (keyspace, 
                                                      columnFamily,
                                                      StringSerializer.get(), 
                                                      StringSerializer.get());
       return builtTemplate;
   }

   ...
}

我看到的唯一选择是将Factory类型的对象保持不变,即不使方法静态。

如果要从应用程序中删除“新”,则需要某种机制来代表您创建对象。 您可能需要检查三种机制。

首先是依赖注入。 DI容器使您可以采用基于接口的方法,并选择在运行时使用哪些实现。 Spring是最受欢迎的DI容器,而CDI是新的“标准”容器。 DI很好,但是不一定要在项目后期引入。

第二种机制是Java ServiceLoader,它允许您通过从类路径中添加和删除文件来更改组件的实现。 您可能会发现这一点。

最后一种机制是使用静态方法(!!!!)读取属性,该属性是工厂对象的类名,并使用Class.forName()。newInstance()为您创建工厂对象。 这可能是最简单的方法。 它给您一个接缝,以注入新的模拟工厂。

避免静电是一个好主意,但是它们有自己的位置。 如果您了解所涉及的取舍,请使用它们。

您无需显式创建工厂。

将新实例的创建提取到类中的受保护方法中,与创建工厂方法完全相同,只是提供new ThriftColumnFamilyTemplate(...)作为默认实现。

在单元测试中,sut将是类的部分模拟版本,模拟了工厂方法,而不是真实的类。 使用这种方法,未​​经测试的唯一代码将是工厂方法,即一行。 对于部分模拟,您可以使用EasyMock IMockBuilder

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM