我这么问是因为我想用嘲弄的框架(的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()
但这似乎只是额外的开销。 任何人都可以解释为什么这是不好的,如果有一个更好的解决方案,以使该方法的非静态的,这样我可以使用模拟框架存根出这些方法(不仅仅是去除关键字等)?
谢谢!
静态方法的问题是,他们是非常难以伪造时,他们不相关,你想对系统进行测试。 想象一下这样的代码:
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
试想一下这样做,当该方法是静态的。 我真的不能想办法,除了修改记录仪有一个叫做静态变量inTestMode
您在设置为true setUp()
以确保它没有连接到数据库。
它采用模块化设计少。 相反,你应该定义一个接口ApiCaller
用一个实例方法makeHttpCall()
这样就可以在未来的定义不同的实现。
在最起码,你将永远有一个接口,原始和嘲笑的版本2级的实现。
(注:也有一些嘲讽的框架,让你嘲笑静态方法)
作为附录,而这可能不是您的具体应用的情况下,通常采用静态方法表明一个更大的设计监督。 设计为模块化和可重用性应该是整个应用程序中普遍存在,因为即使你不需要它,现在你可能需要在未来,这是非常困难和耗费更多的时间在事后改变的事情。
私有静态辅助方法不坏,其实,他们实际上是在大公司,我的工作首选。 我用用的Mockito他们所有的时间,从调用静态辅助方法的方法来访问。
有一个在编译器是怎样对待一个静态辅助方法略有区别。 创建的字节代码将导致invokestatic指令,如果你删除静态的结果将是其他的指令之一,像invokespecial。 差存在在于invokestatic加载类来访问方法,其中第一invokespecial弹出对象堆栈。 所以有可能是轻微的性能优势(也许不是)。
这时候,你需要你不能轻易嘲笑他们几乎回答了你自己的问题。
特别是当它是如图所示的东西:让一个HTTP调用是昂贵的,而且这样做的单元测试代码是没有意义的保存,对于集成测试。
单元测试需要从HTTP调用的东西,如果你调用别人的服务,用你无法控制的网络,你不能做已知响应(和响应代码)。