मैं एक परिदृश्य में जहाँ हम Supplier<LocalDate>
बजाय LocalDate
का उपयोग करना चाहिए के माध्यम से जाना होगा ।
कोड कि सीधे LocalDate.now()
की तरह स्थिर तरीकों को कॉल करता है इकाई परीक्षण करने के लिए बहुत मुश्किल है।
class Person {
final String name;
private final LocalDate dateOfBirth;
Person(String name, LocalDate dateOfBirth) {
this.name = name;
this.dateOfBirth = dateOfBirth;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, LocalDate.now());
}
}
यह उत्पादन में ठीक काम करता है: एक विधि getAge()
कि एक व्यक्ति की आयु की गणना करता है परीक्षण एक परिदृश्य में जहाँ हम इकाई के लिए चाहते हैं पर विचार करें। लेकिन एक यूनिट टेस्ट को या तो सिस्टम की तारीख को किसी ज्ञात मूल्य पर सेट करना होगा या हर साल अपडेट किया जाना चाहिए ताकि वापसी की उम्र एक के द्वारा बढ़ाया जा सके, दोनों बहुत ही भयानक समाधान।
एक बेहतर समाधान इकाई परीक्षण एक ज्ञात तारीख में इंजेक्ट करने के लिए, जबकि अभी भी उत्पादन कोड LocalDate.now()
उपयोग करने की अनुमति होगी। शायद इस तरह कुछ:
class Person {
final String name;
private final LocalDate dateOfBirth;
private final LocalDate currentDate;
// Used by regular production code
Person(String name, LocalDate dateOfBirth) {
this(name, dateOfBirth, LocalDate.now());
}
// Visible for test
Person(String name, LocalDate dateOfBirth, LocalDate currentDate) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.currentDate = currentDate;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, currentDate);
}
}
उस परिदृश्य पर विचार करें जहां ऑब्जेक्ट बनाया गया था, व्यक्ति का जन्मदिन बीत चुका है। इस कार्यान्वयन के साथ, getAge()
उस समय पर आधारित होगा जब व्यक्ति ऑब्जेक्ट को वर्तमान दिनांक की बजाय बनाया गया था। हम Supplier<LocalDate>
का उपयोग करके इस का समाधान कर सकते हैं:
class Person {
final String name;
private final LocalDate dateOfBirth;
private final Supplier<LocalDate> currentDate;
// Used by regular production code
Person(String name, LocalDate dateOfBirth) {
this(name, dateOfBirth,()-> LocalDate.now());
}
// Visible for test
Person(String name, LocalDate dateOfBirth, Supplier<LocalDate> currentDate) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.currentDate = currentDate;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, currentDate.get());
}
public static void main(String... args) throws InterruptedException {
// current date 2016-02-11
Person person = new Person("John Doe", LocalDate.parse("2010-02-12"));
printAge(person);
TimeUnit.DAYS.sleep(1);
printAge(person);
}
private static void printAge(Person person) {
System.out.println(person.name + " is " + person.getAge());
}
}
उत्पादन सही ढंग से होगा:
@Test
void testGetAge() {
Supplier<LocalDate> injectedNow =()-> LocalDate.parse("2016-12-01");
Person person = new Person("John Doe", LocalDate.parse("2004-12-01"), injectedNow);
assertEquals(12, person.getAge());
}
's2':
हमारी इकाई परीक्षण" अब "इस तरह की तारीख इंजेक्षन कर सकते हैं उस बिंदु पर आपको "अब" देगा जहां 's2' असाइन किया गया था। 's1.get() 'आपको उस बिंदु पर" अब "देगा जब आप' get()' को कॉल करते हैं। यह तब भी नहीं हो सकता है जब आप आवश्यक होने पर कहीं भी 'प्रदायक' का उपयोग कर चुके हों। फिर यदि आप बाद में 's1.get()' को कॉल करते हैं, तो आपको फिर से एक अलग समय मिल जाएगा। – khelwood
@ शेल्ववुड, मुझे यह नहीं मिला और प्रश्न अपडेट किया गया, कृपया जांचें। – badCoder
इसका उपयोग तब करें जब आपको _multiple values_ को _another method_ में प्राप्त करने की क्षमता पारित करने की आवश्यकता हो ._ यह वैध उपयोग मामलों में से 100% है। –