2015-02-24 47 views
1

我試圖嘲笑DateTimeFormatter類。我已經做了以下情況:模擬java.time.format.DateTimeFormatter類

@RunWith(PowerMockRunner.class) 
@PrepareForTest({DateTimeFormatter.class}) 
public class UnitTest { 

private DateTimeFormatter mockDateFormatter; 

private AwesomeClass awesomeClass; 

@Before 
public void setUp() { 
    mockDateFormatter = PowerMockito.mock(DateTimeFormatter.class); 
    awesomeClass = new AwesomeClass(mockDateFormatter); 
} 

@Test 
public void shouldToTestSomethingAwesome() { 
    // Other test code 
    PowerMockito.when(mockDateFormatter.format(any(LocalDate.class))) 
        .thenReturn("20150224"); 
    // Other test code 

} 

AwesomeClass使用它來格式化LocalDateTime.now(ZoneId.of("UTC"));。格式化的字符串然後被進一步用於生成另一個字符串。我需要確保字符串正確生成。所以我需要從格式化程序返回一致的日期或模擬LocalDateTime.now(..)靜態方法

我在做什麼錯了?

+6

*爲什麼*你想模擬'DateTimeFormatter',出於興趣?你爲什麼不用一個真正的?我會對過分嘲諷保持警惕 - 它會使測試變得更加脆弱(並且難以閱讀),而不是簡單地使用真實的代碼或者具有大致相同行爲的假貨。 – 2015-02-24 13:47:11

+1

聽起來像單元測試運行模擬我... – duffymo 2015-02-24 13:47:47

+0

我通過格式化程序的類使用它來格式LocalDateTime.now(ZoneId.of(「UTC」));'。格式化的字符串然後被進一步用於生成另一個字符串。我需要確保字符串正確生成。所以我需要從格式化程序返回一致的日期或模擬'LocalDateTime.now(..)'靜態方法 – 2015-02-24 13:54:08

回答

4

以嘲諷LocalDateTime.now()的替代方法是將時鐘注入類和改變你的(或添加其他)構造是這樣的:

AwesomeClass(DateTimeFormatter fmt, Clock clock) { 
    //instead of LocalDateTime now = LocalDateTime.now(): 
    LocalDateTime now = LocalDateTime.now(clock); 
} 
在測試

然後:

new AwesomeClass(formatter, Clock.fixed(the time you want here)); 
+1

所建議的方法。如果不清楚,爲測試目的添加第二個構造函數(包私有)是完全合理的。例如,您現有的構造函數可以被修改爲使用參數'Clock.systemUTC()'來調用包私有的構造函數。 – 2015-02-24 14:41:26

8

在mockito wiki:Don't mock types you don't own !

這不是硬件裏ne,但是通過這條線可能會產生影響! (很有可能)。

  1. 想象一下嘲笑第三方庫的代碼。在第三個庫的特定升級之後,邏輯可能會改變一點,但測試套件將會執行得很好,因爲它被嘲弄。所以,以後想,一切都很好走,牆壁是綠色的,畢竟軟件部署和... 繁榮
  2. 這可能是一個跡象,目前的設計是不夠脫離這第三黨的圖書館。
  3. 另一個問題是,第三方庫可能很複雜,需要大量的模擬才能正常工作。這會導致過度指定的測試和複雜的裝置,這本身就影響了緊湊且可讀的目標。或者由於模擬外部系統的複雜性,測試不足以覆蓋代碼。

相反,最常見的方式是圍繞着外部的lib /系統創建包裝,但應該意識到抽象泄漏,其中太多底層API,概念或異常的風險,去超越邊界的包裝。爲了驗證與第三方庫的集成,編寫集成測試,並使其儘可能緊湊和可讀。

,你沒有控制模擬類型可以被認爲是(嘲諷)反模式。雖然DataTimeFormatter幾乎是標準,但我們不應該認爲即將到來的JDK版本中不會有任何行爲改變(它已經在API的其他部分發生過無數次了,只是看JDK發行說明)。我的觀點是,如果代碼需要模擬一種我不擁有的類型,那麼設計應該改變asap,所以我,我的同事或這個代碼的未來維護者不會落入這些陷阱。

此外,wiki鏈接到其他博客條目,描述他們試圖模擬他們沒有控制的類型時遇到的問題。

+0

這是2018年,你的鏈接已經死亡。這個答案是什麼意思?誰知道! – 2015-02-24 14:29:30

+0

@Duncan不是它不是 – Brice 2015-02-24 14:35:29

+0

要麼從你的答案中加入一些來自該頁面的信息,或者將它改爲在問題下的評論,其中相同的質量規則不適用。鏈接**做**休息,所以有一天你的答案可能只是讀取「*不要嘲笑你不擁有的類型!*」,這沒有什麼幫助。 – 2015-02-24 14:36:50