अभिकथन जूनिट में 2 सूचियों के बीच बराबर होता है


165

मैं JUnit परीक्षण मामले में सूचियों के बीच समानता का दावा कैसे कर सकता हूं ? सूची की सामग्री के बीच समानता होनी चाहिए।

उदाहरण के लिए:

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
List<String> numbers3 = Arrays.asList("one", "two", "four"); 

// numbers should be equal to numbers2
//numbers should not be equal to numbers3

5
मुझे assertArrayEqualsआजकल इस्तेमाल करना पसंद है। के साथ संयोजन में उपयोग करें List#toArray
थिबस्टार

@ थिबस्टार - मुझे लगता है कि एक जवाब के रूप में upvote होगा।
dfrankow

2
assertArrayEqualsआपको अपनी सूचियों से एरेज़ प्राप्त करने की आवश्यकता है। आप का उपयोग कर सीधे सूची पर काम कर सकते हैंassertIterableEquals
ThetaSinner

assertIterableEqualsjUnit5 @ThetaSinner के लिए उपलब्ध है
iec2011007

जवाबों:


170

मुझे लगता है कि यह कुछ साल पहले पूछा गया था, शायद यह सुविधा तब आसपास नहीं थी। लेकिन अब, ऐसा करना आसान है:

@Test
public void test_array_pass()
{
  List<String> actual = Arrays.asList("fee", "fi", "foe");
  List<String> expected = Arrays.asList("fee", "fi", "foe");

  assertThat(actual, is(expected));
  assertThat(actual, is(not(expected)));
}

यदि आपके पास हैमरेस्ट के साथ जूनिट का हाल का संस्करण स्थापित है, तो बस इन आयातों को जोड़ें:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html


3
System.out.println(actual == expected);झूठी आएगी, लेकिन System.out.println(actual.equals(expected));सच लौटेगी।
कैटफ़िश

@ कैटफ़िश हाँ, यह भ्रामक है। मुझे लगता है कि मैं यह प्रदर्शित कर रहा था कि मैचर्स .equals(..)इसके बजाय उपयोग कर रहा है ==?
djeikyb

2
यह मुखर से बेहतर कैसे है?
राडवल्ड

1
जब दावा विफल होता है तो @Rawalwal आउटपुट। मैं अंतर में संपादित करने के लिए बाद में वापस आने की कोशिश करूंगा। हैमरेस्ट मैचर्स विस्तृत विफलता संदेश उत्पन्न कर सकते हैं। यह संभव है कि समान भलाई के साथ यह जोर से ओवरलोड करने के लिए जूनट के लिए संभव है। लेकिन ज्यादातर जूनिट कोर यूनिट टेस्ट सुविधाएँ प्रदान करता है, और हैमरेस्ट एक अच्छा-से-ऑब्जेक्ट ऑब्जेक्ट डिस्क्रिप्शन लाइब्रेरी प्रदान करता है।
djeikyb

29

स्ट्रिंग और तुलना करने के लिए बदल नहीं है। यह परफ्यूम के लिए अच्छा नहीं है। Corematchers के अंदर जूनियर में, इसके लिए एक मिलानकर्ता है =>hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)    
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));

यह बेहतर तरीका है कि मैं किसी सूची में तत्वों की जांच करना जानता हूं।


2
एक नोट के साथ चुना हुआ उत्तर होना चाहिए: आपको यह भी सत्यापित करने की आवश्यकता है कि सूची में और आइटम नहीं हैं जो आप चाहते हैं। हो सकता है कि का उपयोग करें:Assert.assertEquals(4,yourList.size());
योनि

या एक ही लाइन के साथ:assertThat(yourList.toArray(), arrayContainingInAnyOrder(1,2,3,4,5));
user1778602

3
"यह पूर्णता के लिए अच्छा नहीं है।" → मुझे यकीन नहीं है कि यूनिट टेस्ट लिखते समय किसी को किस डिग्री पर ध्यान देना चाहिए ... लेकिन यकीन है, स्ट्रिंग्स की उनके toString()संस्करण के माध्यम से तुलना करना सबसे अच्छा तरीका नहीं है।
Walen

21

यह एक विरासत का जवाब है, जो जुनीत 4.3 और नीचे के लिए उपयुक्त है। JUnit के आधुनिक संस्करण में मुखर विधि में एक अंतर्निहित पठनीय विफलता संदेश शामिल हैं। यदि संभव हो तो इस सवाल पर अन्य उत्तरों को प्राथमिकता दें।

List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
            "\n  'a'        = "+a+
            "\n  'expected' = "+expected, 
            expected.equals(a));

रिकॉर्ड के लिए, @Paul ने इस उत्तर के लिए अपनी टिप्पणी में उल्लेख किया, दो Listएस बराबर हैं:

यदि और केवल यदि निर्दिष्ट ऑब्जेक्ट भी एक सूची है, तो दोनों सूचियों का आकार समान है, और दो सूचियों में तत्वों के सभी संगत जोड़े समान हैं। (दो तत्व e1और e2समान हैं यदि (e1==null ? e2==null : e1.equals(e2))।) दूसरे शब्दों में, दो सूचियों को समान रूप से परिभाषित किया जाता है यदि वे समान क्रम में समान तत्व रखते हैं। यह परिभाषा सुनिश्चित करती है कि Listइंटरफ़ेस के विभिन्न कार्यान्वयनों में समान पद्धति ठीक से काम करती है ।

इंटरफ़ेस के JavaDocsList देखें ।


1
तो आप उम्मीद कर रहे हैं। असमान (ए) उन वस्तुओं पर जोर देने का ध्यान रखेगा जो सूची पकड़े हुए हैं?
कमल

1
सूची javadoc से: समानता के लिए इस सूची के साथ निर्दिष्ट ऑब्जेक्ट की तुलना करता है। यह सच है कि अगर और केवल निर्दिष्ट ऑब्जेक्ट भी एक सूची है, तो दोनों सूचियों का आकार समान है, और दो सूचियों में सभी संगत जोड़े समान हैं। (दो तत्व e1 और e2 समान हैं यदि (e1 == null? E2 == null: e1.equals (e2))। दूसरे शब्दों में, दो सूचियों को समान रूप से परिभाषित किया जाता है यदि उनमें समान तत्व समान क्रम में हों। । यह परिभाषा सुनिश्चित करती है कि सूची इंटरफ़ेस के विभिन्न कार्यान्वयनों में समान पद्धति ठीक से काम करती है।
पॉल मैकेंजी

1
यह अफसोस सहायक त्रुटि संदेश से कम प्रदान करता है। मैंने उपयोगिता वर्ग लिखना बेहतर समझा है जो एक लूप करता है ताकि आप देख सकें कि कौन से तत्व अलग हैं।
माइकल लॉयड ली mlk

@mlk, शायद, लेकिन मैं ऐसी बात के लिए एक कस्टम उपयोगिता विधि लिखने में संकोच कर रहा हूं। मैंने अभी जो त्रुटि संदेश संपादित किया है, उसके बारे में क्या?
बार्ट कीर्स

@ mlk मैं सहमत हूं कि प्रत्येक तत्व का परीक्षण करने के लिए लूप लिखना बेहतर हो सकता है ताकि आपको पता चले कि वास्तव में क्या अलग है। यह निर्भर करता है कि सूची में किस प्रकार की वस्तुएं हैं। यदि वे स्ट्रिंग्स हैं, तो बस "a =" + को ठीक होना चाहिए, लेकिन यदि वे जटिल वस्तुएं हैं (अन्य सूचियाँ, या ऐसा कुछ जो एक अच्छा स्थैतिक कार्यान्वयन नहीं है), तो उन्हें व्यक्तिगत रूप से जांचना आसान हो सकता है
मैट एन

20

assertEquals(Object, Object)JUnit4 से / JUnit 5 या assertThat(actual, is(expected));Hamcrest से अन्य उत्तर में प्रस्तावित केवल दोनों के रूप में काम करेंगे equals()औरtoString() तुलना वस्तुओं के वर्गों (और गहराई से) के लिए overrided कर रहे हैं।

यह मायने रखता है क्योंकि दावे में समानता परीक्षण निर्भर करता है equals()और परीक्षण विफलता संदेश toString()तुलनात्मक वस्तुओं पर निर्भर करता है ।
अंतर्निहित कक्षाओं के लिए जैसे कि String, Integerऔर इसलिए ... इन दोनों के रूप में कोई समस्या नहीं है equals()और toString()। तो यह पूरी तरह से मान्य है List<String>या List<Integer>साथ assertEquals(Object,Object)
और इस मामले के बारे में: आपको equals()एक वर्ग में ओवरराइड करना होगा क्योंकि यह वस्तु समानता के संदर्भ में समझ में आता है, न केवल JUnit के साथ एक परीक्षण में जोर देना।
कथनों को आसान बनाने के लिए आपके पास अन्य तरीके हैं।
एक अच्छे अभ्यास के रूप में मैं दावे / मिलान पुस्तकालयों का पक्ष लेता हूं।

यहाँ एक AssertJ समाधान है।

org.assertj.core.api.ListAssert.containsExactly() आपको जो चाहिए वह है: यह पुष्टि करता है कि वास्तविक समूह में दिए गए मान बिल्कुल हैं और कुछ और नहीं, जैसा कि जवादोक में कहा गया है।

एक Fooवर्ग मान लीजिए कि आप कहां तत्व जोड़ते हैं और आप कहां से प्राप्त कर सकते हैं।
इस बात का एक इकाई परीक्षण Fooयह दावा करता है कि दो सूचियों में एक जैसी सामग्री हो सकती है:

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception { 
   Foo foo = new Foo();
   foo.add("One", "Two", "Three");
   Assertions.assertThat(foo.getElements())
             .containsExactly("One", "Two", "Three");
}

एक AssertJ अच्छी बात यह है कि एक Listउम्मीद के रूप में घोषित करना अनावश्यक है: यह जोर को कठोर बनाता है और कोड अधिक पठनीय है:

Assertions.assertThat(foo.getElements())
         .containsExactly("One", "Two", "Three");

लेकिन जोर / मिलान पुस्तकालयों एक चाहिए क्योंकि ये वास्तव में आगे होगा।
अब मान लीजिए कि s लेकिन इंस्टेंस को Foo स्टोर नहीं करता है । यह एक बहुत ही आम जरूरत है। AssertJ के साथ अभिकथन अभी भी लिखना सरल है। बेहतर होगा कि आप सूची सामग्री को बराबर कर सकते हैं भले ही तत्वों का वर्ग ओवरराइड नहीं करता हो, जबकि JUnit रास्ते के लिए यह आवश्यक है:StringBar
equals()/hashCode()

import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
    Foo foo = new Foo();
    foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
    Assertions.assertThat(foo.getElements())
              .extracting(Bar::getId, Bar::getName)
              .containsExactly(tuple(1, "One"),
                               tuple(2, "Two"),
                               tuple(3, "Three"));
}

7

यदि आप तत्वों के क्रम के बारे में परवाह नहीं करते हैं, तो मैं ListAssert.assertEqualsजूनियर-एडन में सलाह देता हूं ।

लिंक: http://junit-addons.sourceforge.net/

आलसी मावेन उपयोगकर्ताओं के लिए:

    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>

7
नोट: यदि आप तत्वों के क्रम की परवाह नहीं करते हैं, तो आपको एक सूची में नहीं, एक सेट या संग्रह का उपयोग करना चाहिए।
बरेट

11
मैं सहमत हूँ। यह पुस्तकालय स्थूल है। धरती पर क्यों ListAssert.assertEquals () क्रमहीन के लिए डिफ़ॉल्ट होगा?
रयान

5

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

import org.junit.Assert;   
import org.junit.Test;

    @Test
    public void test_array_pass()
    {
        List<String> actual = Arrays.asList("fee", "fi", "foe");
        List<String> expected = Arrays.asList("fee", "fi", "foe");
        Assert.assertEquals(actual,expected);
    }

यदि तत्वों का क्रम अलग है तो यह त्रुटि लौटाएगा।

यदि आप एक मॉडल ऑब्जेक्ट सूची में प्रवेश कर रहे हैं, तो आपको विशिष्ट मॉडल में बराबर पद्धति को ओवरराइड करना चाहिए।

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj != null && obj instanceof ModelName) {
            ModelName other = (ModelName) obj;
            return this.getItem().equals(other.getItem()) ;
        }
        return false;
    }

4

यदि आप एक सरणी सूची नहीं बनाना चाहते हैं, तो आप यह भी कोशिश कर सकते हैं

@Test
public void test_array_pass()
{
  List<String> list = Arrays.asList("fee", "fi", "foe");
  Strint listToString = list.toString();
  Assert.assertTrue(listToString.contains("[fee, fi, foe]"));   // passes  
}


1

पहिया को मजबूत मत करो!

एक Google कोड लाइब्रेरी है जो आपके लिए ऐसा करती है: Hamcrest

[हैमरेस्ट] मैचर ऑब्जेक्ट्स (जिन्हें अड़चन या विधेय के रूप में भी जाना जाता है) की एक लाइब्रेरी प्रदान करता है, जिससे 'मैच' के नियमों को घोषित रूप से परिभाषित किया जा सके, जिसका उपयोग अन्य रूपरेखाओं में किया जा सके। विशिष्ट परिदृश्यों में टेस्टिंग फ्रेमवर्क, मॉकिंग लाइब्रेरी और UI सत्यापन नियम शामिल हैं।


0

मुझे पता है कि इस मुद्दे को हल करने के लिए पहले से ही कई विकल्प हैं, लेकिन मैं किसी भी ओडर में दो सूचियों को शामिल करने के लिए निम्नलिखित करना चाहूंगा :

assertTrue(result.containsAll(expected) && expected.containsAll(result))

यदि यह आदेश से मेल नहीं खाता है तो यह विफल नहीं होगा ??
Iec2011007

0

assertEquals(expected, result);मेरे लिये कार्य करता है। चूंकि इस फ़ंक्शन को दो ऑब्जेक्ट मिलते हैं, आप इसे कुछ भी पास कर सकते हैं।

public static void assertEquals(Object expected, Object actual) {
    AssertEquals.assertEquals(expected, actual);
}

-1

मुझे नहीं लगता कि उपरोक्त सभी उत्तर ऑब्जेक्ट्स की दो सूचियों की तुलना करने के लिए सटीक समाधान दे रहे हैं। उपरोक्त दृष्टिकोणों में से अधिकांश केवल तुलना की सीमा का पालन करने में सहायक हो सकते हैं - आकार की तुलना - संदर्भ तुलना

लेकिन अगर हमारे पास वस्तुओं के आकार और वस्तुओं के स्तर पर अलग-अलग डेटा हैं, तो यह तुलना दृष्टिकोण मदद नहीं करेगा।

मुझे लगता है कि निम्नलिखित दृष्टिकोण पूरी तरह से उपयोगकर्ता-परिभाषित वस्तु पर बराबरी और हैशकोड विधि के साथ काम करेगा।

मैंने ओवरराइड बराबरी और हैशकोड के लिए एक्सस्ट्रीम लिब का इस्तेमाल किया था, लेकिन हम बराबरी से और हैशकोड को ओवरराइड कर सकते हैं और साथ ही लॉजिक या तुलना भी जीत सकते हैं।

यहाँ आपके संदर्भ के लिए उदाहरण है

    import com.thoughtworks.xstream.XStream;

    import java.text.ParseException;
    import java.util.ArrayList;
    import java.util.List;

    class TestClass {
      private String name;
      private String id;

      public void setName(String value) {
        this.name = value;
      }

      public String getName() {
        return this.name;
      }

      public String getId() {
        return id;
      }

      public void setId(String id) {
        this.id = id;
      }

      /**
       * @see java.lang.Object#equals(java.lang.Object)
       */
      @Override
      public boolean equals(Object o) {
        XStream xstream = new XStream();
        String oxml = xstream.toXML(o);
        String myxml = xstream.toXML(this);

        return myxml.equals(oxml);
      }

      /**
       * @see java.lang.Object#hashCode()
       */
      @Override
      public int hashCode() {
        XStream xstream = new XStream();
        String myxml = xstream.toXML(this);
        return myxml.hashCode();
      }
    }

    public class XstreamCompareTest {
      public static void main(String[] args) throws ParseException {
      checkObjectEquals();
}

      private static void checkObjectEquals() {
        List<TestClass> testList1 = new ArrayList<TestClass>();
        TestClass tObj1 = new TestClass();
        tObj1.setId("test3");
        tObj1.setName("testname3");
        testList1.add(tObj1);

        TestClass tObj2 = new TestClass();
        tObj2.setId("test2");
        tObj2.setName("testname2");
        testList1.add(tObj2);

        testList1.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));

        List<TestClass> testList2 = new ArrayList<TestClass>();
        TestClass tObj3 = new TestClass();
        tObj3.setId("test3");
        tObj3.setName("testname3");
        testList2.add(tObj3);

        TestClass tObj4 = new TestClass();
        tObj4.setId("test2");
        tObj4.setName("testname2");
        testList2.add(tObj4);

        testList2.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));

        if (isNotMatch(testList1, testList2)) {
          System.out.println("The list are not matched");
        } else {
          System.out.println("The list are matched");
        }

      }

      private static boolean isNotMatch(List<TestClass> clist1, List<TestClass> clist2) {
        return clist1.size() != clist2.size() || !clist1.equals(clist2);
      }
    }

सबसे महत्वपूर्ण बात यह है कि यदि आप ऑब्जेक्ट्स के बराबर चेक पर किसी फ़ील्ड को शामिल नहीं करना चाहते हैं, तो आप एनोटेशन (@XStreamOmitField) द्वारा फ़ील्ड्स को अनदेखा कर सकते हैं। कॉन्फ़िगर करने के लिए इस तरह के कई एनोटेशन हैं, इसलिए इस परिवाद के एनोटेशन के बारे में गहराई से देखें।

मुझे यकीन है कि यह उत्तर वस्तुओं की दो सूचियों की तुलना के लिए सही दृष्टिकोण की पहचान करने के लिए आपके समय की बचत करेगा :)। यदि आपको इस पर कोई समस्या दिखाई देती है तो कृपया टिप्पणी करें।

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