2 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超5個(gè)贊
終于有時(shí)間更深入地研究這個(gè)問題了。
我開始實(shí)驗(yàn),過了一段時(shí)間后發(fā)現(xiàn),實(shí)際上并不是System.out.println它的存在影響了結(jié)果,而是你LocalDateTime在它之前實(shí)例化了2個(gè)實(shí)例。
深入挖掘LocalDateTime和SystemClock(它所委托的) 的代碼,我發(fā)現(xiàn)亞毫級(jí)精度是通過調(diào)用本機(jī)調(diào)用 來實(shí)現(xiàn)的jdk.internal.misc.VM#getNanoTimeAdjustment。
最后一個(gè)調(diào)用是特定于操作系統(tǒng)的。我對(duì)它進(jìn)行了一些實(shí)驗(yàn),發(fā)現(xiàn)它不會(huì)線性返回值,因?yàn)樗谘h(huán)中被調(diào)用(假設(shè)我的循環(huán)運(yùn)行得相當(dāng)規(guī)律)。
所以我決定運(yùn)行一些代碼來映射返回的納米值。
我制作了這個(gè)示例代碼:
Clock clock = Clock.systemDefaultZone();
int samples = 1_000;
LocalDateTime[] instants = new LocalDateTime[samples];
int k = 0;
for (int i = 0; i < samples; i++) {
instants[i] = LocalDateTime.now(clock);
for (int j = 0; j < 10000; j++) {
k = j % 2;
}
}
將值寫入文件,然后將納米差異與第一個(gè)值映射到圖表中:
正如您所看到的,該圖(包含 1000 個(gè)值)會(huì)出現(xiàn)間歇性跳躍。這顯然部分是由于底層系統(tǒng)的精度限制造成的。但令我震驚的是,前兩個(gè)值始終不同。就好像在定期訪問時(shí)操作系統(tǒng)開始緩存該值一段時(shí)間(可能是為了避免系統(tǒng)資源緊張)。
但結(jié)果似乎是您設(shè)置自己在第三次和第四次調(diào)用時(shí)獲得相同的值(除非已經(jīng)過去了足夠的時(shí)間)。
這可以解釋為什么您的測(cè)試在沒有這些先前實(shí)例的情況下通過,而失敗。
順便說一句,對(duì)于單元測(cè)試,您不想依賴系統(tǒng)時(shí)鐘。確保您的業(yè)務(wù)代碼從注入的 Clock 實(shí)例獲取時(shí)間。然后,您可以注入自定義時(shí)鐘進(jìn)行測(cè)試,并測(cè)試您的代碼是否會(huì)在 DST 轉(zhuǎn)換日期或閏日運(yùn)行,而無需等待幾個(gè)月。

TA貢獻(xiàn)1847條經(jīng)驗(yàn) 獲得超7個(gè)贊
該測(cè)試涉及競(jìng)爭(zhēng)條件并通過(有時(shí)),因?yàn)闀r(shí)間和添加語(yǔ)句會(huì)改變時(shí)間并因此改變測(cè)試結(jié)果。
斷言中檢查的條件基本上是連續(xù)兩個(gè)日期時(shí)間的納秒部分是否相等。
鑒于默認(rèn)情況下由System.currentTimeMillis()
內(nèi)部使用并且它最多具有毫秒精度,如果獲取納秒數(shù)的第二個(gè)調(diào)用序列足夠快(即導(dǎo)致在同一時(shí)間內(nèi)完成調(diào)用的LocalDateTime.now
實(shí)際調(diào)用序列),則檢查將成功。System.currentTimeMillis
毫秒作為第一個(gè))。
當(dāng)您在實(shí)際斷言之前調(diào)用用于獲取納秒值的函數(shù)時(shí),會(huì)加載相應(yīng)的類,相應(yīng)方法的代碼會(huì)進(jìn)入 CPU 緩存等。這使得第二對(duì)獲取納秒數(shù)的調(diào)用運(yùn)行得更快。
添加回答
舉報(bào)