2

A lot of code needs to use some global flag or properties to control the flow of the application. It is necessary for a lot of scenarios to maintain a Dynamic Cache which will have a flag to lock/unlock a particular piece of (new)code.

For all such scenarios I usually write this way:

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

}

DynamicPropery is a Singleton which periodically refreshes the cache from the DB.
The problem with this is Unit testing is little tricky, so far I've used Jmockit to get around that - and it works fine.
But I was wondering if there can be a better way to write a method like that that can be easier for Unit testing.

4

3 回答 3

3

您可以以某种方式隔离所有属性检索,PropertyResolverBean然后将其注入您的 SUT 并替换静态调用:

private PropertyResolverBean injectedPropertyResolverBean;

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

}

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

您最终会得到遵循 SRP 规则的更易于维护、可读性和可测试性更高的代码。

于 2019-06-08T09:32:27.807 回答
2

一般来说,应该尽可能避免硬编码的全局常量。由于您需要模拟/切换依赖项,因此将其方法定义为静态很难完成,因为它将类的客户端与前缀为的静态类强耦合。
当然,您可能需要在应用程序中维护全局状态,但没有什么能阻止您将其定义为一个对象,您可以将其作为依赖项注入到他们需要的类中:

private DynamicProperty dynamicProperty;

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

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

这对于依赖注入是相当直接的,但您可以使用普通的构造函数或 setter 调用自己完成。
当然,您应该将静态方法更改为实例方法,以允许以自然方式模拟调用。

于 2019-06-08T09:32:56.430 回答
0

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

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

那么你的调用代码变成:

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

这样你并没有真正改变太多,你只是在需要时获得动态属性,所以你不需要担心那部分,现在你可以轻松地测试你的方法。

这基本上称为函数式编码,您删除依赖项并仅将数据传递给一个方法,这意味着该方法现在没有依赖项,并且可以通过注入您想要的任何值来轻松测试。

如果你有更多这样的值,我会创建一个单独的类并将它们全部分组到一个地方,从中创建一个接口,将其传递给类构造函数,然后以这种方式使用它。我可能不会只为一个值这样做,除非它真的简化了你的代码。

于 2019-06-08T11:38:43.260 回答