为什么在Java中使用静态辅助方法不好?

odi*_*ity 21 java android static-methods helpermethods mockito

我问,因为我试图使用一个模拟框架(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;
   }
}
Run Code Online (Sandbox Code Playgroud)

要使用这一切,我所要做的就是调用ApiCaller.makeHttpCall(url) Now我可以很容易地将它变为非静态方法,如:

public class ApiCaller {
...
   public String makeHttpCall(Url url) {
        // Performs logic to retrieve response and deal with custom server errors
        ...
        return response;
   }
}
Run Code Online (Sandbox Code Playgroud)

然后使用此方法调用,new ApiCaller().makeHttpCall()但这似乎是额外的开销.任何人都可以解释为什么这是坏的,如果有一个更好的解决方案使方法非静态(除了删除关键字),以便我可以使用模拟框架存根这些方法?

谢谢!

Dan*_*lan 9

静态方法的问题是,当它们与您尝试测试的系统无关时,它们很难伪造.想象一下这段代码:

public void systemUnderTest() {
    Log.connectToDatabaseForAuditing();
    doLogicYouWantToTest();
}
Run Code Online (Sandbox Code Playgroud)

connectToDatabaseForAuditing()方法是静态的.您不关心此方法对您要编写的测试的作用.但是,要测试此代码,您需要一个可用的数据库.

如果它不是静态的,代码看起来像这样:

private Logger log; //instantiate in a setter AKA dependency injection/inversion of control

public void systemUnderTest() {
    log.connectToDatabaseForAuditing();
    doLogicYouWantToTest();
}
Run Code Online (Sandbox Code Playgroud)

现在,在没有数据库的情况下编写测试将是微不足道的:

@Before
public void setUp() {
    YourClass yourClass = new YourClass();
    yourClass.setLog(new NoOpLogger());

}

//.. your tests
Run Code Online (Sandbox Code Playgroud)

想象一下,当方法是静态的时,尝试这样做.我无法想到一种方法,除了修改记录器以使一个静态变量被调用inTestMode,你设置为true setUp()以确保它不连接到数据库.

  • 我从一个嘲弄的角度理解为什么有必要不使用静态方法,但我或多或少想弄清楚为什么很多人都说使用静态方法是糟糕的编程习惯(例如http://blogs.msdn .COM/b/nickmalik /存档/ 2005/09/06/461404.aspx).也许这是一个足够好的理由,所有代码都应该是可测试的.. (2认同)