2010-08-11 100 views
14

我正在爲我正在處理的項目中的一些實用程序類設置單元測試,其中一個類(包含許可信息)有一個方法根據當前時間做出一些確定。在當前時間使用條件處理單元測試

即,許可證包含到期日期,並且許可證字符串驗證該日期,但查看許可證是否過期的實際邏輯基於當前時間。

public boolean isValid() 
{ 
    return isLicenseStringValid() && !isExpired(); 
} 

public boolean isExpired() 
{ 
    Date expiry = getExpiryDate(); 
    if(expiry == null) { 
     return false; 
    } 

    Date now = new Date(); 

    return now.after(expiry); 
} 

因此,我不知道該怎麼做,因爲'new Date()'事物不是靜態標準。

  1. 我不應該費心去測試'isValid',只是單獨測試'isLicenseStringValid()'和'getExpiryDate()'函數?
  2. 難道我只是在測試中使用許可證密鑰並且瘋狂的長期到期,以至於我將在其到期時間之前切換作業?
  3. 我是否試圖將'new Date()'模擬成某種'getCurrentTime()'方法,以便我可以僞造現在的時間?

其他人通常對時間有條件的測試做什麼?

+0

BTW,我看比迄今爲止其他邏輯代碼的一個問題: 如果(到期== NULL){ 返回FALSE; } 如果失效日期爲空,我認爲你不應該在'isExpired()'方法返回'false'。 欲瞭解更多信息,請閱讀 - https://www.owasp.org/index.php/Fail_securely – Garbage 2013-03-03 14:40:39

+0

這是一個許可證對象,有兩種可能的模式: 1.永久無期限(因此上述) 2.臨時有效期爲 因此,如果沒有到期日期設定,則不會過期。 – 2013-03-04 14:55:57

回答

23

肯定模擬出new Date()

使用getCurrentTime()方法或類似方法創建一個Clock接口。這樣你可以有FakeClock進行測試,SystemClock可以使用System.currentTimeMillis()或其他。

我已經完成了很多次 - 它工作得非常好。這也是合乎邏輯的 - 實際上你需要一個「當前時間服務」,以便像任何其他依賴項那樣注入。

+0

謝謝,使用DI感覺有點奇怪,感覺它是語言本身的一部分,但聽起來像這樣會起作用。 – 2010-08-11 14:55:28

5

我通常將日期提供程序注入測試代碼。如果您需要切換約定或以其他方式「修復」時間測試代碼,這也有幫助。

2

使用依賴注入並注入提供getExpiryDate()方法的TimeProvider

1

三種方法是可能的:

  1. 沒有測試:懶惰的人的方式
  2. 使用,直到你離開了工作,不會爲年齡到期的許可證:包括我的屁股的方式
  3. 使用模擬當前日期,如TimeProvider:完美主義的方式

我會去一個comprimise:我想補充當前日期作爲參數傳遞給isExpired方法,並和isValid方法。對於您的現場製作代碼,請添加一個調用isValid(new Date())的簡單isValid()無參數覆蓋。您的測試代碼使用將當前日期作爲參數的版本。

+0

這個選項我最喜歡。如果語言支持默認參數,則會更容易一些。 – elias 2013-07-23 14:18:29

2

如果你覺得TimeProvider /時鐘抽象是太過分的完美主義者(這很可能是這種情況),認爲這不是

讓getCurrentType受保護的虛擬,然後創建一個包含代碼的ProductionType的TestingProductionType decendant你發佈了。在該類型中,重寫getCurrentType()方法以返回一些確定性結果。在你的單元測試中,改爲創建一個這個TestingProductionType的實例。

中提琴,當前時間的依賴關係現在從您的單元測試中刪除。現在沒有進行單元測試的唯一生產代碼是使用單行返回新Date()的方法。我可以忍受這一點。