[英]Time dependent unit tests
我需要測試一個函數,其結果將取決於當前時間(使用 Joda 時間的isBeforeNow()
,它發生了)。
public boolean isAvailable() {
return (this.someDate.isBeforeNow());
}
是否可以使用(例如,使用 Mockito)存根/模擬系統時間,以便我可以可靠地測試該功能?
使您的代碼可測試的最佳方法 (IMO) 是將“當前時間是什么”的依賴關系提取到其自己的接口中,並使用使用當前系統時間(正常使用)的實現和允許您設置時間的實現,根據需要推進它等。
我在各種情況下都使用過這種方法,而且效果很好。 它很容易設置 - 只需創建一個界面(例如Clock
),該界面具有單一方法,可以以您想要的任何格式(例如使用 Joda Time 或可能的Date
)為您提供當前時刻。
Joda 時間支持通過DateTimeUtils
類的setCurrentMillisFixed
和setCurrentMillisOffset
方法設置“假”當前時間。
見https://www.joda.org/joda-time/apidocs/org/joda/time/DateTimeUtils.html
Java 8 引入了抽象類java.time.Clock
,它允許您有一個替代的測試實現。 這正是喬恩當時在他的回答中所建議的。
要添加到Jon Skeet 的答案中,Joda Time 已經包含一個當前時間接口: DateTimeUtils.MillisProvider
例如:
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils.MillisProvider;
public class Check {
private final MillisProvider millisProvider;
private final DateTime someDate;
public Check(MillisProvider millisProvider, DateTime someDate) {
this.millisProvider = millisProvider;
this.someDate = someDate;
}
public boolean isAvailable() {
long now = millisProvider.getMillis();
return (someDate.isBefore(now));
}
}
在單元測試中模擬時間(使用Mockito,但您可以實現自己的類 MillisProviderMock):
DateTime fakeNow = new DateTime(2016, DateTimeConstants.MARCH, 28, 9, 10);
MillisProvider mockMillisProvider = mock(MillisProvider.class);
when(mockMillisProvider.getMillis()).thenReturn(fakeNow.getMillis());
Check check = new Check(mockMillisProvider, someDate);
在生產中使用當前時間( DateTimeUtils.SYSTEM_MILLIS_PROVIDER在 2.9.3 中被添加到 Joda 時間):
Check check = new Check(DateTimeUtils.SYSTEM_MILLIS_PROVIDER, someDate);
我使用了一種類似於 Jon 的方法,但不是只為當前時間創建一個專門的接口(比如Clock
),我通常創建一個特殊的測試接口(比如MockupFactory
)。 我把測試代碼所需的所有方法都放在那里。 例如,在我的一個項目中,我有四種方法:
被測試的類有一個構造函數,它在其他參數中接受這個接口。 沒有這個參數的只是創建了這個界面的一個默認實例,它可以“在現實生活中”工作。 接口和構造函數都是包私有的,因此測試 API 不會泄漏到包之外。
如果我需要更多模仿對象,我只需向該接口添加一個方法並在測試和實際實現中實現它。
通過這種方式,我首先設計了適合測試的代碼,而不會對代碼本身施加太多影響。 事實上,由於大量的工廠代碼集中在一個地方,因此代碼變得更加清晰。 例如,如果我需要在實際代碼中切換到另一個數據庫客戶端實現,我只需要修改一行,而不是四處尋找對構造函數的引用。
當然,就像 Jon 的方法一樣,它不適用於您無法或不允許修改的 3rd 方代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.