AssertEquals 2 सूचियाँ आदेश की अनदेखी करती हैं


82

मेरा मानना ​​है कि वास्तव में सरल प्रश्न होना चाहिए। लेकिन किसी तरह मुझे Google में जवाब नहीं मिल रहा है।

मान लें कि मेरे पास स्ट्रिंग्स की 2 सूची है। पहले में "स्ट्रिंग ए" और "स्ट्रिंग बी" होता है , दूसरे में "स्ट्रिंग बी" और "स्ट्रिंग ए" (नोटिस क्रम में अंतर) होता है। मैं उन्हें जाँचने के लिए JUnit के साथ परीक्षण करना चाहता हूं कि क्या उनमें समान स्ट्रिंग्स हैं।

क्या कोई ऐसा जोर है जो स्ट्रिंग्स की समानता की जांच करता है जो आदेश की अनदेखी करता है? दिए गए उदाहरण के लिए। org.junit.Assert.assertEquals जोर देता है

java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]>

चारों ओर काम करने के लिए सूचियों को पहले क्रमबद्ध करना है और फिर उन्हें मुखर करना है। लेकिन मैं चाहता हूं कि मेरा कोड यथासंभव सरल और साफ हो।

मैं Hamcrest 1.3 , JUnit 4.11 , Mockito 1.9.5 का उपयोग करता हूं


3
list1.removeAll(list2)list1खाली छोड़ देना चाहिए । मुझे लगता है कि आप इस पर निर्माण कर सकते हैं कि आप क्या चाहते हैं।
सुदोहरूल

6
containsAllऔर removeAllकर रहे हैं O(n²), जबकि उन्हें और परीक्षण छँटाई समानता है के लिए सूचियों के लिए O(nlogn)Collections.sort(list1); Collections.sort(list2); assertTrue(list1.equals(list2));साफ भी है।
एलेक्सिस सी।


@SudoRahul - यदि आप सभी को हटाकर किसी सूची को संशोधित नहीं करना चाहते हैं तो क्या होगा?
एर्रान मोराद

@BoratSagdiyev - चूँकि ओपी की ओर से कोई अड़चन नहीं थी, इसलिए मैंने सुझाव दिया। लेकिन अगर वह अड़चन है, तो इस सवाल का स्वीकृत जवाब हाथ में समस्या का हल है।
सुदोहरूल

जवाबों:


92

जैसा कि आप उल्लेख करते हैं कि आप Hamcrest का उपयोग करते हैं, मैं संग्रह मिलानकर्ताओं में से एक को चुनूंगा

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.junit.Assert.assertThat;

public class CompareListTest {

    @Test
    public void compareList() {
        List<String> expected = Arrays.asList("String A", "String B");
        List<String> actual = Arrays.asList("String B", "String A");

        assertThat("List equality without order", 
            actual, containsInAnyOrder(expected.toArray()));
    }

}

5
यह भी देखें मेरा उत्तर stackoverflow.com/a/38262680/297710 जो दिखाता है, कैसे साथ containsInAnyOrder हर दर्शाते हैं उनमें Hamcrest matchers और से बचने के ".toArray ()" में सुधार करने के
yvolk

58

आप जाँच कर सकते हैं कि JUnit के दावे के साथ List.containsAll का उपयोग यह जांचने के लिए कर सकते हैं कि पहली सूची में दूसरे तत्व से प्रत्येक तत्व है, और इसके विपरीत।

assertTrue(first.size() == second.size() && 
    first.containsAll(second) && second.containsAll(first));

2
@kukis यह निर्भर करता है, क्या आप डुप्लिकेट की जांच करना चाहते हैं?
रॉबर्टो

4
हां बिल्कुल। 2 दी गई सूचियां ठीक उसी तरह होनी चाहिए जैसे कि केवल अनदेखा आदेश।
kukis

2
@kukis अपने सवाल पर ZouZou की टिप्पणी की जाँच करें।
रोबर्टोआ

1
..माइट में शामिल assertEquals(first.size(), second.size())हैं..तो यह उम्मीद के मुताबिक काम करना चाहिए
निश्चित रूप से अपरिहार्य

17
यह सूची में डुप्लिकेट के साथ काम नहीं करता है। यहाँ एक उदाहरण प्रदर्शित करने के लिए है: List<String> list1 = Arrays.asList("a", "a", "b"); List<String> list2 = Arrays.asList("a", "b", "b"); assertEquals(list1.size(), list2.size()); assertTrue(list1.containsAll(list2) && list2.containsAll(list1)); इस उदाहरण में, दोनों दावे यह पता लगाने में विफल हैं कि सूचियाँ वास्तव में अलग हैं। @AlexWorden ने अपाचे कॉमन्स कलेक्शंस के कलेक्शन यूटिल्स.इसेक्वालकोलेक्शन () का उल्लेख किया है, जो इस उदाहरण के लिए, सही ढंग से पता लगाता है कि संग्रह समान नहीं हैं।
desilvai

11

यहां एक समाधान है जो द्विघात जटिलता से बचा जाता है (कई बार सूचियों पर पुनरावृत्ति)। यह सूची में प्रत्येक आवृत्ति के लिए प्रत्येक आइटम का मानचित्र बनाने के लिए Apache Commons CollectionUtils वर्ग का उपयोग करता है। यह तो बस दो नक्शे की तुलना करता है।

Assert.assertEquals("Verify same metrics series",
    CollectionUtils.getCardinalityMap(expectedSeriesList),
    CollectionUtils.getCardinalityMap(actualSeriesList));

मैं भी सिर्फ CollectionUtils.isEqualCollection है कि यहाँ क्या अनुरोध किया जा रहा है दावा करने के लिए देखा ...

https://commons.apache.org/proper/commons-collections/apidocs/index.html?org/apache/commons/collections4/CollectionUtils.html


4

AssertJ के साथ, containsExactlyInAnyOrder()या containsExactlyInAnyOrderElementsOf()आपको क्या चाहिए:

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

import java.util.Arrays;
import java.util.List;

public class CompareListTest {

    @Test
    public void compareListWithTwoVariables() {
        List<String> expected = Arrays.asList("String A", "String B");
        List<String> actual = Arrays.asList("String B", "String A");
        Assertions.assertThat(actual)
                  .containsExactlyInAnyOrderElementsOf(expected);
    }

    @Test
    public void compareListWithInlineExpectedValues() {
        List<String> actual = Arrays.asList("String B", "String A");
        Assertions.assertThat(actual)
                  .containsExactlyInAnyOrder("String A", "String B");
    }    
}


2

मैं पार्टी में देर से आया हूं, लेकिन यहां मेरा समाधान केवल जूनित का उपयोग करना है। किसी भी विचार का स्वागत है।

List<String> actual = new ArrayList<>();
actual.add("A");
actual.add("A");
actual.add("B");

List<String> expected = new ArrayList<>();
actual.add("A");
actual.add("B");
actual.add("B");

//Step 1: assert for size
assertEquals(actual.size(), expected.size());

//Step 2: Iterate
for(String e: expected){
    assertTrue(actual.contains(e));
    actual.remove(e);
}

1

ध्यान दें कि रॉबर्टो इज़िकिएर्डो द्वारा समाधान में सामान्य रूप से द्विघात जटिलता है। हैशसेट पर समाधान में हमेशा रैखिक जटिलता होती है:

assertTrue(first.size() == second.size() &&
        new HashSet(first).equals(new HashSet(second)));

2
यह दृष्टिकोण काम नहीं करेगा। अगर पहला है ("स्ट्रिंग ए") और दूसरा है ("स्ट्रिंग ए", "स्ट्रिंग ए") वे समान सूची नहीं हैं।
एलेक्सिस सी।

4
आप आकार की जांच नहीं कर सकते। यदि पहला है ("s1", "s2", "s3" ,"s1")और दूसरा है तो ("s2", "s1", "s3" ,"s2");वे समान सूची नहीं हैं।
एलेक्सिस सी।

@ZouZou स्वीकृत समाधान में एक ही समस्या है। आपने एकमात्र सही समाधान सुझाया। यदि आप एक उत्तर देते हैं तो मैं इसे बढ़ा दूंगा।
लेवेंटोव

@ZouZou वे एक ही सूची नहीं हैं, लेकिन वे वास्तव में एक ही तार होते हैं। ओपी, स्पष्ट करें ?. इसके अलावा, यह एक जवाब है और मैं भी upvote होगा :) के बारे में सोचा नहीं था।
रोबर्टोआ

2
यह अभी भी सभी मामलों के लिए सही नहीं है ("ए", "ए", "बी") की तुलना "ए (" ए "," बी "," बी ") के बराबर होगी
टिम बी

1

एक त्वरित सुधार के लिए मैं दोनों तरीकों की जाँच करूँगा:

assertTrue(first.containsAll(second));
assertTrue(second.containsAll(first));

और ऐसी स्थिति में प्रयास करना जहाँ समान तत्वों की संख्या भिन्न हो (उदाहरण 1, 1, 2 और 1, 2, 2) मुझे झूठी सकारात्मकता नहीं मिली।


1
आपका कोड अभी भी विफल है। इस उदाहरण को देखें - @Test public void test1 () {सूची <string> list1 = Arrays.asList ("a", "a", "b"); सूची <string> list2 = Arrays.asList ("a", "b", "b"); Assert.assertTrue (list1.containsAll (list2)); Assert.assertTrue (list2.containsAll (list1)); }
एर्रन मुराद


0

ऐसा लगता है कि अन्य उत्तर या तो तीसरे पक्ष के बर्तनों का संदर्भ देते हैं, गलत हैं, या अक्षम हैं।

यहाँ जावा 8 में O (N) वनीला घोल दिया गया है।

public static void assertContainsSame(Collection<?> expected, Collection<?> actual)
{
    assert expected.size() == actual.size();

    Map<Object, Long> counts = expected.stream()
        .collect(Collectors.groupingBy(
                item -> item,
                Collectors.counting()));

    for (Object item : actual)
        assert counts.merge(item, -1L, Long::sum) != -1L;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.