簡體   English   中英

java:如何模擬 Calendar.getInstance()?

[英]java: how to mock Calendar.getInstance()?

在我的代碼中,我有這樣的東西:

private void doSomething() {
   Calendar today = Calendar.getInstance();
   ....
}

如何在我的 junit 測試中“模擬”它以返回特定日期?

你可以使用PowerMock和Mockito一起模擬它:

在課堂上:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})

成功的關鍵是你必須將類放在PrepareForTest中使用Calendar而不是Calendar本身,因為它是一個系統類。 (在我發現這個之前,我個人不得不經常搜索)

然后是嘲弄本身:

mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);

據我所知,你有三個合理的選擇:

  1. 以您在當天設置的任何方法/類中注入Calendar實例。

    private void method(final Calendar cal) { Date today = cal.getTime(); }

  2. 使用JodaTime而不是Calendar 這不是一個選擇,而是一個建議的案例,因為JodaTime將使您的生活更輕松。 您仍需要將此時間注入方法。

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. 在一些允許您獲取時間的界面中包裝Calendar 然后,您只需模擬該接口並使其返回一個常量Date

    Date today = calendarInterfaceInstance.getCurrentDate()

不要嘲笑它 - 而是引入一個你可以模擬得到日期的方法。 像這樣的東西:

interface Utility {

    Date getDate();
}

Utilities implements Utility {


    public Date getDate() {

        return Calendar.getInstance().getTime();
    }

}

然后你可以將它注入到你的類中,或者只使用帶有一堆靜態方法的helper類和一個load方法:

public class AppUtil {

    private static Utility util = new Utilities();

    public static void load(Utility newUtil) {

         this.util = newUtil;
    }

    public static Date getDate() {

        return util.getDate();
    }

}

然后在您的應用程序代碼:

private void doSomething() {
   Date today = AppUtil.getDate();
   ....
}

然后,您可以在測試方法中加載模擬接口。

@Test
public void shouldDoSomethingUseful() {
     Utility mockUtility = // .. create mock here
     AppUtil.load(mockUtility);

     // .. set up your expectations

     // exercise the functionality
     classUnderTest.doSomethingViaAPI();

     // ... maybe assert something 

}

另請參閱您是否只能模擬您擁有的類型? 測試氣味 - 一切都被嘲笑

使用Mockito和PowerMockito:

Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);

有關完整代碼,請參閱鏈接

編寫一個叫做類DateHelper與方法getCalendar返回Calendar.getInstance() 重構您正在測試的類,使其具有DateHelper類型的成員變量,以及注入該成員變量的構造函數。 使用該構造在您的測試,注入的模擬DateHelper ,其中getCalendar已存根返回一些已知的日期。

你可以使用JMockit進行模擬。 在這里,您可以看到如何做到這一點: 模擬Java日歷 - JMockit與Mockito

避免使用Calendar.getInstance()並僅使用Mockito方法返回您喜歡的內容。 例如:

@Test
fun italianLocale_returnsItalianFormatDate() {
    val calendar: Calendar = Mockito.mock(Calendar::class.java)
    Mockito.`when`(calendar.get(Calendar.DAY_OF_MONTH)).thenReturn(27)
    Mockito.`when`(calendar.get(Calendar.YEAR)).thenReturn(2023)
    Mockito.`when`(calendar.get(Calendar.MONTH)).thenReturn(1)
    val formatted = calendar.toReadableDate()
    assert(formatted == "27/01/2023")
}

在您的 gradle 文件中導入 Mockito:

testImplementation ("org.mockito.kotlin:mockito-kotlin:x.x.x")

或者(如果你使用的是 groovy)

testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM