我问这个问题是因为我正在尝试使用一个模拟框架(Mockito),它不允许你模拟静态方法。看了看,我发现有相当多的博客文章说你应该尽可能少使用静态方法,但我很难理解为什么。特别是为什么方法不会修改全局状态,而且基本上都是辅助方法。例如,我有一个名为ApiCaller
的类,它有几个静态方法。静态方法的目的之一是执行HTTP调用,处理服务器可能返回的任何自定义问题(例如。用户未登录)并返回响应。为了简单起见,就像这样:
public class ApiCaller {
...
public static String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
要使用它,我所要做的就是调用ApiCaller.makeHttpCall(url)
,现在我可以很容易地将它变成一个非静态方法,比如:
public class ApiCaller {
...
public String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
然后调用new ApiCaller().makeHttpCall()
来使用这个方法,但这似乎是额外的开销。有没有人可以解释为什么这很糟糕,是否有更好的解决方案来使方法成为非静态的(而不仅仅是删除关键字),这样我就可以使用mocking框架将这些方法存根出来?
谢谢!
发布于 2013-01-18 04:19:09
静态方法的问题是,当它们与您试图测试的系统无关时,它们很难伪造。想象一下这段代码:
public void systemUnderTest() {
Log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
connectToDatabaseForAuditing()
方法是静态的。你并不关心这个方法对你想要写的测试做了什么。但是,现在要测试这段代码,您需要一个可用的数据库。
如果它不是静态的,代码将如下所示:
private Logger log; //instantiate in a setter AKA dependency injection/inversion of control
public void systemUnderTest() {
log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
现在,在没有数据库的情况下编写测试将是微不足道的:
@Before
public void setUp() {
YourClass yourClass = new YourClass();
yourClass.setLog(new NoOpLogger());
}
//.. your tests
想象一下,当方法是静态的时,你会尝试这样做。除了将记录器修改为在setUp()
中将名为inTestMode
的静态变量设置为true以确保它不连接到数据库之外,我实在想不出其他方法。
发布于 2017-02-19 01:34:50
私有静态帮助器方法还不错,事实上,在我工作的大公司里,它们实际上是首选的方法。我一直对它们使用Mockito,从调用静态帮助器方法的方法访问。
编译器处理静态帮助器方法的方式略有不同。创建的字节码将导致invokestatic指令,如果您删除静态指令,结果将是其他指令之一,如invokespecial。不同之处在于invokestatic加载类来访问方法,而invokespecial首先从堆栈中弹出对象。因此,可能会有轻微的性能优势(可能没有)。
https://stackoverflow.com/questions/14387385
复制相似问题