एक निश्चित संपत्ति वाले तत्वों में एक Iterable कैसे सम्मिलित करता है?


103

मान लें कि मैं इस हस्ताक्षर के साथ एक विधि का परीक्षण करना चाहता हूं:

List<MyItem> getMyItems();

मान लें MyItemकि एक पूजो है जिसमें कई गुण हैं, जिनमें से एक के "name"माध्यम से पहुँचा जाता है getName()

मुझे इस बात की परवाह है कि सत्यापन के लिए दो List<MyItem>या Iterableदो MyItemउदाहरण हैं, जिनके "name"गुणों में मूल्य "foo"और हैं "bar"। यदि कोई अन्य गुण मेल नहीं खाते हैं, तो मैं वास्तव में इस परीक्षण के उद्देश्यों की परवाह नहीं करता हूं। यदि नाम मेल खाते हैं, तो यह एक सफल परीक्षा है।

मैं चाहूंगा कि अगर संभव हो तो वन-लाइनर बनना चाहिए। यहाँ कुछ "छद्म-वाक्य-विन्यास" है जिस तरह की चीज़ मैं करना चाहता हूँ।

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"});

क्या इस प्रकार की चीज के लिए हैमरेस्ट अच्छा होगा? यदि हां, तो वास्तव में ऊपर मेरे छद्म वाक्य-विन्यास का हैमरेस्ट संस्करण क्या होगा?

जवाबों:


125

धन्यवाद @Razvan जिन्होंने मुझे सही दिशा में इशारा किया। मैं इसे एक पंक्ति में लाने में सक्षम था और मैंने Hamcrest 1.3 के आयात का सफलतापूर्वक शिकार किया।

आयात:

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;

कोड:

assertThat( myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar"))
));


46

इसकी विशेष रूप से हैमरेस्ट नहीं है, लेकिन मुझे लगता है कि यह यहाँ उल्लेख के लायक है। Java8 में मैं अक्सर जो उपयोग करता हूं वह कुछ इस प्रकार है:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));

(रोड्रिगो मनारी के मामूली सुधार का संपादन। यह थोड़ा कम क्रिया है। टिप्पणियों को देखें।)

यह पढ़ने में थोड़ा कठिन हो सकता है, लेकिन मुझे टाइप और रिफैक्टिंग सुरक्षा पसंद है। इसके संयोजन में कई बीन गुणों के परीक्षण के लिए भी अच्छा है। फिल्टर लैम्ब्डा में एक जावा-जैसे और& अभिव्यक्ति के साथ।


2
थोड़ा सा सुधार:।। AssertTrue (myClass.getMyItems () धारा () anyMatch (मद -> "foo" .equals (item.getName ()));
रॉड्रिगो Manyari

@RodrigoManyari, बंद कोष्ठक गायब
अब्दुल

1
यह समाधान एक उपयुक्त त्रुटि संदेश दिखाने की संभावना को बर्बाद करता है।
गिउलिओ कैसिन

@GiulioCaccin मुझे नहीं लगता कि यह करता है। यदि आप JUnit का उपयोग करते हैं, तो आप ओवरलोड किए गए दावे के तरीकों का उपयोग कर सकते हैं / लिख सकते हैं और मुखर लिख सकते हैं (..., "मेरा अपना परीक्षण विफलता संदेश"); Junit.org/junit5/docs/current/api/org/junit/jupiter/api/…
मारियो ईस

मेरा मतलब है, यदि आप एक बूलियन के खिलाफ जोर देते हैं, तो आप वास्तविक / अपेक्षित अंतर को स्वचालित रूप से प्रिंट करने की क्षमता खो देते हैं। एक मिलानकर्ता का उपयोग करना मुखर करना संभव है, लेकिन आपको इसे करने के लिए इस पृष्ठ में अन्य के समान होने के लिए इस प्रतिक्रिया को संशोधित करने की आवश्यकता है।
Giulio Caccin

20

इस पर असरज अच्छा है।

import static org.assertj.core.api.Assertions.assertThat;

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar");

हैमरेस्ट की तुलना में एस्टरज के लिए बिग प्लस कोड पूरा करने का आसान उपयोग है।


16

AssertJ एक उत्कृष्ट सुविधा प्रदान करता है extracting(): आप Functionफ़ील्ड निकालने के लिए s पास कर सकते हैं । यह संकलन समय पर एक चेक प्रदान करता है।
आप पहले आकार को आसानी से परख सकते हैं।

यह देना होगा:

import static org.assertj.core.api.Assertions;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName)
          .containsExactlyInAnyOrder("foo", "bar"); 

containsExactlyInAnyOrder() यह दावा करता है कि सूची में केवल ये मूल्य हैं जो भी आदेश हैं।

यह दावा करने के लिए कि सूची में ये मान शामिल हैं जो भी आदेश हैं लेकिन इसमें अन्य मान भी हो सकते हैं contains():

.contains("foo", "bar"); 

एक साइड नोट के रूप में: ListA के तत्वों से कई फ़ील्ड्स को मुखर करने के लिए, AssertJ के साथ हम एक tuple()फ़ंक्शन में प्रत्येक तत्व के लिए अपेक्षित मानों को लपेटकर करते हैं:

import static org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName, MyItem::getOtherValue)
          .containsExactlyInAnyOrder(
               tuple("foo", "OtherValueFoo"),
               tuple("bar", "OtherValueBar")
           ); 

4
नहीं मिलता है, यह कोई upvotes नहीं है। मुझे लगता है, यह सबसे अच्छा जवाब है, अब तक।
PeMa

1
AssertJ पुस्तकालय बहुत अधिक पठनीय है तो JUnit अभिकथन API।
संगम 10

@ संचित सहमत और भी मैं इसे हैमरेस्ट को पसंद करता हूं।
davidxxx

मेरी राय में यह थोड़ा कम पठनीय है क्योंकि यह "अपेक्षित मूल्य" से "वास्तविक मूल्य" को अलग करता है और उन्हें एक ऐसे क्रम में रखता है जिसे मिलान करने की आवश्यकता होती है।
टेरान

5

जब तक आपकी सूची एक ठोस वर्ग है, तब तक आप सम्‍मिलित () विधि को तब तक कॉल कर सकते हैं जब तक कि आपने MyItem पर अपने बराबर () विधि को लागू नहीं किया है।

// given 
// some input ... you to complete

// when
List<MyItems> results = service.getMyItems();

// then
assertTrue(results.contains(new MyItem("foo")));
assertTrue(results.contains(new MyItem("bar")));

मान लें कि आपने एक निर्माता को लागू किया है जो उन मूल्यों को स्वीकार करता है जिन पर आप जोर देना चाहते हैं। मुझे लगता है कि यह एक लाइन पर नहीं है, लेकिन यह जानना उपयोगी है कि दोनों को एक बार चेक करने के बजाय कौन सा मूल्य गायब है।


1
मुझे वास्तव में आपका समाधान पसंद है, लेकिन क्या उसे परीक्षण के लिए उस सभी कोड को मॉडिफाई करना चाहिए?
केविन बोवर्सॉक्स

मुझे लगता है कि यहां हर उत्तर के लिए कुछ परीक्षण सेटअप, परीक्षण करने की विधि का निष्पादन और फिर गुणों का दावा करना होगा। मेरे जवाब का कोई वास्तविक जवाब नहीं है कि मैं क्या देख सकता हूं, केवल यह कि मेरे पास समुद्री लाइनों पर दो दावे हैं ताकि एक असफल दावे को स्पष्ट रूप से पहचान सकें कि क्या मूल्य गायब है।
ब्रैड

यह भी सबसे अच्छा होगा कि किसी संदेश को जोर के भीतर शामिल करें ताकि त्रुटि संदेश अधिक समझदार हो। किसी संदेश के बिना, यदि यह विफल रहता है, तो JUnit बिना किसी त्रुटि संदेश के केवल AssertionFailedError फेंक देगा। तो कुछ को शामिल करने के लिए सबसे अच्छा है "परिणामों में नया MyItem (\" foo \ ") होना चाहिए"।
मैक्स

हाँ आप सही है। मैं किसी भी मामले में Hamcrest की सिफारिश करूंगा, और मैं इन दिनों मुखर () का उपयोग नहीं करता हूं
ब्रैड

एक तरफ ध्यान दें कि आपके POJO या DTO को समान पद्धति को परिभाषित करना चाहिए
तैयब हुसैन

1

AssertJ 3.9.1 anyMatchविधि में प्रत्यक्ष विधेय उपयोग का समर्थन करता है ।

assertThat(collection).anyMatch(element -> element.someProperty.satisfiesSomeCondition())

यह आम तौर पर मनमाने ढंग से जटिल स्थिति के लिए उपयुक्त उपयोग का मामला है।

सरल परिस्थितियों के लिए मैं extractingविधि का उपयोग करना पसंद करता हूं (ऊपर देखें) क्योंकि परिणामस्वरूप चलने योग्य-परीक्षण बेहतर पठनीयता के साथ मूल्य सत्यापन का समर्थन कर सकता है। उदाहरण: यह containsफ्रैंक नेबंग के उत्तर में विशिष्ट एपीआई जैसे विधि प्रदान कर सकता है । या फिर आप इस anyMatchपर बाद में कॉल कर सकते हैं और विधि संदर्भ का उपयोग कर सकते हैं जैसे कि "searchedvalue"::equals। इसके अलावा कई एक्सट्रैक्टर्स को extractingविधि में डाला जा सकता है , जिसके परिणामस्वरूप बाद में सत्यापित किया जाता है tuple()

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.