एक सामान्य समस्या है: समय का मजाक उड़ाना कठिन है। इसके अलावा, यूनिट परीक्षण में लंबे समय तक चलने / प्रतीक्षा कोड रखने के लिए वास्तव में बुरा अभ्यास है।
इसलिए, शेड्यूलिंग एपीआई को परीक्षण योग्य बनाने के लिए, मैंने इस तरह के एक वास्तविक और नकली कार्यान्वयन के साथ एक इंटरफ़ेस का उपयोग किया:
public interface Clock {
public long getCurrentMillis();
public void sleep(long millis) throws InterruptedException;
}
public static class SystemClock implements Clock {
@Override
public long getCurrentMillis() {
return System.currentTimeMillis();
}
@Override
public void sleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
}
public static class MockClock implements Clock {
private final AtomicLong currentTime = new AtomicLong(0);
public MockClock() {
this(System.currentTimeMillis());
}
public MockClock(long currentTime) {
this.currentTime.set(currentTime);
}
@Override
public long getCurrentMillis() {
return currentTime.addAndGet(5);
}
@Override
public void sleep(long millis) {
currentTime.addAndGet(millis);
}
}
इसके साथ, आप अपने परीक्षण में समय का अनुकरण कर सकते हैं:
@Test
public void testExipres() {
MockClock clock = new MockClock();
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
clock.sleep(2000)
assertNull(sco.getIfNotExpired("foo"));
}
एक उन्नत मल्टी-थ्रेडिंग मॉक Clock
बेशक अधिक जटिल है, लेकिन आप इसे ThreadLocal
संदर्भों और एक अच्छा समय सिंक्रनाइज़ेशन रणनीति के साथ बना सकते हैं , उदाहरण के लिए।
Thread.sleep
कुछ ऐसा कहने के बारे में शिकायत करेंगे जैसे किसी परीक्षण में थ्रेड का उपयोग करना आमतौर पर एक बुरा विचार है। यह भंगुर परीक्षण बनाता है जो पर्यावरण के आधार पर अप्रत्याशित रूप से विफल हो सकता है ("मेरी मशीन पर गुजरता है!") या लोड। समय पर निर्भर न करें (मोक्स का उपयोग करें) या अतुलनीय परीक्षण के लिए वातारण जैसे पुस्तकालयों का उपयोग करें।