2016-03-06 73 views
1

我正在開發一個簡化控制檯應用程序創建的框架。我的框架是用Scala編寫的,我正在使用ScalaTest和Mockito進行單元測試。如何模擬,或以其他方式測試readPassword?

我需要能夠模擬java.io.Console,但它被宣佈是最終的。我試圖達到100%的單元測試覆蓋率,目前這是唯一阻止我的功能和單元測試。

到目前爲止,我還沒有能夠得到任何解決方案很遠,我只是想不到這樣做的一種方式。它沒有實現一個我可以模擬的接口,這個方法在其他地方是不可用的,顯然我不能擴展它。我想也許有一種解決方案,可能涉及某種動態方法調用方法,如readLinereadPassword,但我沒有足夠的經驗去獲得任何地方的這種思路!

+2

100%的覆蓋率是在CS,亞伯拉罕林肯最大的幻想:) –

+0

你有沒有考慮過查看SystemRules(http://stefanbirkner.github.io/system-rules/index.html),它的一套junit處理System類的規則。它可能會給你一些啓發。或者,ScalaCheck可以在這種情況下提供一些幫助,它是一種不同的測試方法。 – Gavin

+0

@SleimanJneidi我毫不懷疑你在那裏是正確的! :)知道這是否有解決方案仍然很有趣,它似乎是Java中API設計的一個疏忽,我還沒有遇到過這樣的事情。 – Seer

回答

0

您應該創建自己的界面來包裝與java.io.Console的所有交互,例如,

public interface ConsoleService { 
    ... 
} 

只要你只通過的ConsoleService實例的控制檯交互,那麼你就可以嘲笑你的代碼的ConsoleService和測試99%,你通常會。接口將成爲應用程序的邊界,用於整個應用程序的功能測試以及直接與其交互的類的單元測試。

現在我們已經將問題的範圍縮小爲「如何測試ConsoleService實施」,我們需要獲得一點創意。例如,您可以將控制檯輸出重定向到一個文件並檢查該文件的內容。您可能甚至不想測試Scala中的ConsoleService;您可以使用ConsoleService編寫一個框架應用程序,然後使用您選擇的腳本語言在您最喜歡的操作系統上啓動一個真正的控制檯,與您的骨架應用程序進行交互並以此方式測試ConsoleService。你可以得到像你這樣的創意(和哈克),因爲:

  1. 它隻影響少量的測試;和
  2. 你的應用程序很可能會成熟到一個點,其中ConsoleService實現不需要改變很多,即你的古怪測試解決方案將不會成爲未來開發人員的重大負擔。

由於這些原因,應該是顯而易見的,這是一個好主意,讓ConsoleService包裝非常薄,因爲沒有任何邏輯將通過奇怪ConsoleService測試進行測試,而不是漂亮的友好斯卡拉測試。通常直接授權到java.io.Console方法已經足夠好了,但您應該允許應用程序的功能測試來驅動接口而不是做出任何推定(您的功能測試斷言可能依賴於與模擬ConsoleService的特定交互,或者可能取決於狀態的一個存根,您可以在測試中控制的ConsoleService的測試實現)。

最後,你可能會認爲ConsoleService包裝是,所以很薄,它的實現確實需要任何單元/功能測試。 ConsoleService的實現可能對您的應用程序非常關鍵,以至於UAT中的應用程序的集成測試或手動檢查將暴露任何缺陷。

也許最終你會像這樣的東西(抱歉,我不說話斯卡拉所以它的Java):

public class RealConsoleService implements ConsoleService { 
    private final java.io.Console delegate; 
    public RealConsoleService(java.io.Console delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public String readLine() throws IOError { 
     return delegate.readLine(); 
    } 
} 

兩個有趣的點:

  • 這就是爲什麼一個很好的例子測試驅動開發幫助編寫靈活的代碼。如果你想用另一種輸入輸出方法重寫你的框架,你只需將ConsoleService重命名爲更抽象的ApplicationInputOutputService並插入不同的實現。
  • 相同的概念可用於測試使用其他難以測試的API的應用程序。許多Java有用的文件IO方法都是靜態方法,因此很難在測試中進行控制。通過如上所述的界面包裝,您的應用程序功能變得易於測試。
相關問題