Spring環(huán)境下靜態(tài)方法的mock

其實(shí)我不是很理解為什么用了Spring還需要使用靜態(tài)方法來提供單例之類的服務(wù)。也許是傳承自較老的代碼,也許對(duì)Spring對(duì)象的生命周期不太肯定,也許要與不屬于Spring上下文的代碼共享邏輯??傊F(xiàn)實(shí)常常還是能看到這種代碼的。

/**
*提供靜態(tài)方法的類
*/
public class PersonPool {
    private static PersonPool instance;
    static {
        instance = new PersonPool();
    }
    private PersonPool() {
        // ...
    }
    public static PersonPool getInstance() {
        return instance;
    }
    public String next() {
        throw new RuntimeException("resource not available in test");
    }
}
/**
*使用靜態(tài)方法的服務(wù)
*/
public class SampleService {
    public String greeting() {
        String name = PersonPool.getInstance().next();
        return "Hello " + name;
    }
}

一旦這些靜態(tài)方法中用到了環(huán)境相關(guān),需要在測(cè)試中隔離的資源,寫單元測(cè)試就時(shí)就會(huì)遇到困難。
這類代碼是無法用mockito來mock的。PowerMock可以mock靜態(tài)方法,不過使用中會(huì)發(fā)現(xiàn)會(huì)給測(cè)試引入更多的細(xì)節(jié),這些細(xì)節(jié)都是妨礙表達(dá)測(cè)試意圖的噪音。
而且往往mock掉方法本身,又發(fā)現(xiàn)類初始化有個(gè)坑……,一點(diǎn)點(diǎn)解決下去,最后測(cè)試湊合能跑起來,但是充滿了各種和實(shí)現(xiàn)緊密耦合的細(xì)節(jié)。實(shí)現(xiàn)代碼里兩行換個(gè)順序,也許測(cè)試就不工作了。

其實(shí)這種處境,往往是因?yàn)楸е?strong>“不能為了測(cè)試修改實(shí)現(xiàn)代碼”的信念造成的。
如果拋開這個(gè)假設(shè),對(duì)代碼稍作修改,測(cè)試就不再是個(gè)問題了。

/**
*提供靜態(tài)方法的類保持不變
*/
public class PersonPool {...}
/**
*增加適配類
*/
@Component
public class PersonPoolProvider {
    public PersonPool getInstance() {
        return PersonPool.getInstance();
    }
}
/**
*改用自動(dòng)注入的適配對(duì)象
*/
public class SampleService {
    @Autowired
    PersonPoolProvider personPoolProvider;

    public String greeting() {
        String name = personPoolProvider.getInstance().next();
        return "Hello " + name;
    }
}

可以看到只需要對(duì)實(shí)現(xiàn)代碼進(jìn)行影響很小的修改:

  • 未改變?cè)徐o態(tài)方法的執(zhí)行邏輯和生命周期。
  • 不影響其它使用靜態(tài)方法的代碼。
  • 適配類足夠簡(jiǎn)單,無需測(cè)試。

希望這不是個(gè)為遺留代碼補(bǔ)測(cè)試的權(quán)宜之計(jì),而是進(jìn)一步改進(jìn)已有代碼的開端。
有以下問題可以探討:

  • util類、方法是否應(yīng)該有某種資源的所有權(quán)?
  • 現(xiàn)實(shí)中單個(gè)存在的事物是否就一定用單例實(shí)現(xiàn)?
  • 使用單例時(shí),是在用它“單個(gè)實(shí)例”的保證,還是在利用可以從類名獲得實(shí)例的“可訪問性”?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,644評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,279評(píng)論 6 342
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,044評(píng)論 2 59
  • 1.先上一張圖,koa中的洋蔥處理機(jī)制 同步:提交請(qǐng)求->等待服務(wù)器處理->處理完畢返回 這個(gè)期間客戶端瀏覽器不能...
    qqqc閱讀 227評(píng)論 0 2
  • MVP模式 model(模型) - view(視圖) - Presenter(管理器),view層不能直接引用mo...
    JSUED閱讀 1,287評(píng)論 0 0

友情鏈接更多精彩內(nèi)容