如何使使用全局动态属性的代码可测试?

时间:2019-06-08 09:22:33

标签: java unit-testing junit dependency-injection testability

许多代码需要使用一些全局标志或属性来控制应用程序的流程。在许多情况下,必须维护一个动态缓存,该缓存将具有用于锁定/解锁特定(新)代码段的标志。

对于所有这种情况,我通常都是这样写的:

''' 
void someMethod(Data data){
  if(DynamicProperty.getValue("OK"))
    // Do Something

}

DynamicPropery是一个Singleton,它定期从数据库刷新缓存。
这样做的问题是单元测试有点棘手,到目前为止,我已经使用 Jmockit 解决了这个问题-并且工作正常。
但是我想知道是否有更好的方法来编写像这样对单元测试更容易的方法。

3 个答案:

答案 0 :(得分:3)

您可以将所有属性检索隔离为某种PropertyResolverBean,然后将其插入到SUT中并替换静态调用:

private PropertyResolverBean injectedPropertyResolverBean;

void someMethod(Data data){
  if(injectedPropertyResolverBean.getValue("OK"))
    // Do Something

}

然后,您可以使用Mockito的基本功能来模拟该bean并以所需的方式预配置测试。

在遵循SRP规则的最后,您最终得到了更具维护性,可读性和可测试性的代码。

答案 1 :(得分:2)

通常,应尽可能避免使用硬编码的全局常数。当您需要模拟/切换依赖项时,将其方法定义为static会使实现起来很困难,因为它将类的客户端与前缀为static的静态类紧密耦合在一起。
当然,您可能需要在应用程序中维护全局状态,但是没有什么可以阻止您将其定义为可以作为依赖项注入到他们需要的类中的对象:

private DynamicProperty dynamicProperty;

public MyClass(DynamicProperty dynamicProperty){
   this.dynamicProperty = dynamicProperty;           
}

void someMethod(Data data){
  if(dynamicProperty.getValue("OK"))
    // Do Something
}

这对于依赖项注入来说非常简单,但是您可以使用简单的构造函数或setter调用来自己实现。
当然,您应该将静态方法更改为实例方法,以允许自然地模拟调用。

答案 2 :(得分:0)

最简单的方法是事先提取值,并在需要时将其传递给方法。

void someMethod(Data data,SomeProperty dynamicProperty){
  if( dynamicProperty whatever)
    // Do Something
}

然后您的呼叫代码变为:

SomeProperty dynamicProperty = DynamicProperty.getValue("OK");    
someMethod(data, dynamicProperty);

这样,您实际上并不需要做太多更改,就可以在需要时获得动态属性,因此您不必担心那部分,现在您可以轻松地测试方法了。

这基本上被称为函数编码,您删除依赖项,仅将数据传递给方法,这意味着该方法现在摆脱了依赖项,可以通过注入所需的任何值轻松地对其进行测试。

如果您还有更多这些值,那么我将创建一个单独的类并将它们全部分组在一个位置,从中创建一个接口,将其传递给类构造函数,然后以这种方式使用它。我可能不会只为一个值执行此操作,除非它确实可以简化您的代码。