मैं समान पद्धति के बिना दो वर्गों पर समानता का दावा कैसे करूं?


111

कहो कि मेरे पास एक वर्ग है जिसमें कोई समान () विधि नहीं है, जिसके पास स्रोत नहीं है। मैं उस वर्ग के दो उदाहरणों पर समानता का दावा करना चाहता हूं।

मैं कई दावे कर सकता हूं:

assertEquals(obj1.getFieldA(), obj2.getFieldA());
assertEquals(obj1.getFieldB(), obj2.getFieldB());
assertEquals(obj1.getFieldC(), obj2.getFieldC());
...

मुझे यह समाधान पसंद नहीं है क्योंकि मुझे पूर्ण समानता की तस्वीर नहीं मिलती है यदि एक प्रारंभिक मुखर विफल रहता है।

मैं स्वयं अपने आप से तुलना कर सकता हूं और परिणाम ट्रैक कर सकता हूं:

String errorStr = "";
if(!obj1.getFieldA().equals(obj2.getFieldA())) {
    errorStr += "expected: " + obj1.getFieldA() + ", actual: " + obj2.getFieldA() + "\n";
}
if(!obj1.getFieldB().equals(obj2.getFieldB())) {
    errorStr += "expected: " + obj1.getFieldB() + ", actual: " + obj2.getFieldB() + "\n";
}
...
assertEquals("", errorStr);

यह मुझे पूर्ण समानता की तस्वीर देता है, लेकिन क्लंकी है (और मैंने संभावित अशक्त समस्याओं का भी हिसाब नहीं दिया है)। एक तीसरा विकल्प है कम्पैक्टर का उपयोग करना, लेकिन तुलना () मुझे यह नहीं बताएगा कि कौन से क्षेत्र समानता में विफल रहे।

क्या एक बेहतर प्रैक्टिस है जिसे मैं ऑब्जेक्ट से चाहता हूं, बिना सबक्लासिंग और ओवरराइडिंग बराबरी (ऊग) के बिना?


क्या आप एक ऐसे पुस्तकालय की तलाश में हैं जो आपके लिए गहरी तुलना करता हो? stackoverflow.com/questions/1449001/… पर सुझाए गए गहरे-बराबर की तरह ?
विकडोर 27-2812

3
आपको यह जानने की आवश्यकता क्यों है कि दोनों उदाहरण समान क्यों नहीं थे। आमतौर पर, equalपद्धति का कार्यान्वयन केवल यह बताता है कि क्या दो उदाहरण समान हैं, और हमें परवाह नहीं है कि इरादे समान क्यों नहीं हैं।
भेश गुरुंग

3
मैं जानना चाहता हूं कि क्या गुण असमान हैं इसलिए मैं उन्हें ठीक कर सकता हूं। :)
रयान नेल्सन

सभी Objectमें एक equalsविधि होती है, आप का मतलब शायद कोई अतिरंजित बराबरी का तरीका नहीं है।
स्टीव कू

सबसे अच्छा तरीका है कि मैं एक रैपर क्लास या एक उपवर्ग का उपयोग कर सकता हूं और फिर बराबरी की विधि को ओवरराइड करने के बाद इसका उपयोग कर सकता
हूं

जवाबों:


66

मॉकिटो एक प्रतिबिंब-मिलान प्रदान करता है:

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

Assert.assertTrue(new ReflectionEquals(expected, excludeFields).matches(actual));

पुराने संस्करणों के लिए:

Assert.assertThat(actual, new ReflectionEquals(expected, excludeFields));

17
यह वर्ग पैकेज में है org.mockito.internal.matchers.apachecommons। मॉकिटो डॉक्स राज्य: org.mockito.internal-> "आंतरिक वर्ग, ग्राहकों द्वारा उपयोग नहीं किया जाना है।" आप इस का उपयोग करके अपनी परियोजना को जोखिम में डाल देंगे। यह किसी भी मॉकिटो संस्करण में बदल सकता है। यहाँ पढ़ें: site.mockito.org/mockito/docs/current/overview-summary.html
luboskrnac

6
Mockito.refEq()इसके बजाय उपयोग करें ।
जेरेमी काओ

1
Mockito.refEq()जब ऑब्जेक्ट में id सेट न हो तो विफल रहता है = (
'16:37 पर' cpolpol)

1
@PiotrAleksanderChmielowski, क्षमा करें, जब स्प्रिंग + जेपीए + एंटिटीज के साथ काम करते हैं, तो एंटिटी ऑब्जेक्ट में एक आईडी (डेटाबेस तालिका के आईडी फ़ील्ड का प्रतिनिधित्व) हो सकता है, इसलिए जब वह खाली हो (डीबी पर एक नया ऑब्जेक्ट अभी तक संग्रहित है), refEqविफल रहता है हैशकोड विधि की तुलना करने के लिए वस्तुओं की तुलना करने में असमर्थ है।
कैविपोलो

3
यह ठीक काम करता है, लेकिन अपेक्षित और वास्तविक गलत क्रम में हैं। होना तो इसका उलटा चाहिए।
पक्कवीक

48

यहां कई सही उत्तर हैं, लेकिन मैं अपना संस्करण भी जोड़ना चाहूंगा। यह असेरज पर आधारित है।

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

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .isEqualToComparingFieldByFieldRecursively(expectedObject);
    }
}

अद्यतन: Assertj v3.13.2 में इस विधि के रूप में पदावनत किया गया है जैसा कि वुड्ज ने टिप्पणी में बताया है। वर्तमान सिफारिश है

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .usingRecursiveComparison()
            .isEqualTo(expectedObject);
    }

}

3
Assertj v3.13.2 में इस विधि बहिष्कृत है और सिफारिश उपयोग करने के लिए अब है usingRecursiveComparison()के साथ isEqualTo(), ऐसा है कि लाइन हैassertThat(actualObject).usingRecursiveComparison().isEqualTo(expectedObject);
Woodz

45

मैं आम तौर पर org.apache.commons.lang3.builder.EqualsBuilder का उपयोग करके इस usecase को लागू करता हूं

Assert.assertTrue(EqualsBuilder.reflectionEquals(expected,actual));

1
ग्रेड: androidTestCompile 'org.apache.commons: कॉमन्स-लैंग 3: 3.5'
Roel

1
जब आप "org.apache.commons.lang3.builder.EqualsBuilder" का उपयोग करना चाहते हैं, तो आपको इसे "निर्भरता" के तहत अपने ग्रेड फ़ाइल में जोड़ना होगा
Roel

3
यह वास्तव में उन क्षेत्रों पर कोई संकेत नहीं देता है जो वास्तव में मेल नहीं खाते हैं।
वडज़िम

1
@Vadzim मैंने नीचे दिए गए कोड का उपयोग किया है ताकि वह Assert.assertEquals (ReflectionToStringBuilder.toString (अपेक्षित), ReflectionToStringBuilder.toString (वास्तविक) प्राप्त कर सके;
अभिजीत कुश

2
इस एक को "समान" और "हैशकोड" लागू करने वाले ग्राफ में सभी नोड्स की आवश्यकता होती है, जो मूल रूप से इस पद्धति को लगभग बेकार कर देते हैं। AssertJ's isEqualToComparingFieldByFieldRecursively मेरे मामले में पूरी तरह से काम कर रहा है।
जॉन झांग

12

मुझे पता है कि यह थोड़ा पुराना है, लेकिन मुझे उम्मीद है कि इससे मदद मिलेगी।

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

इस तरह के प्रश्न का सबसे अधिक मत देने वाला उत्तर (लेखक द्वारा नहीं लिया गया) , आपके लिए सबसे उपयुक्त समाधान है।

मूल रूप से, यह Unitils नामक पुस्तकालय का उपयोग करने पर आधारित है

यह उपयोग है:

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);

जो कक्षा Userको लागू नहीं करता है , तो भी पास हो जाएगा equals()। आप अधिक उदाहरण देख सकते हैं और assertLenientEqualsउनके ट्यूटोरियल में एक बहुत अच्छा मुखर कहा जा सकता है ।


1
दुर्भाग्य से Unitilsलगता है कि मर गया, देखें stackoverflow.com/questions/34658067/is-unitils-project-alive
केन विलियम्स

8

आप Apache commons lang ReflectionToStringBuilder का उपयोग कर सकते हैं

आप या तो उन विशेषताओं को निर्दिष्ट कर सकते हैं, जिन्हें आप एक-एक करके परीक्षण करना चाहते हैं, या बेहतर, जिन्हें आप नहीं चाहते हैं उन्हें बाहर करें:

String s = new ReflectionToStringBuilder(o, ToStringStyle.SHORT_PREFIX_STYLE)
                .setExcludeFieldNames(new String[] { "foo", "bar" }).toString()

आप फिर सामान्य रूप से दो तारों की तुलना करते हैं। प्रतिबिंब के धीमे होने की बात के लिए, मेरा मानना ​​है कि यह केवल परीक्षण के लिए है, इसलिए यह इतना महत्वपूर्ण नहीं होना चाहिए।


1
इस दृष्टिकोण का अतिरिक्त लाभ यह है कि आपको दृश्य आउटपुट मिलते हैं जो अपेक्षित और वास्तविक मूल्यों को प्रदर्शित करते हैं जैसे कि उन क्षेत्रों को छोड़कर जिन्हें आप परवाह नहीं करते हैं।
8

7

यदि आप अपने ऐसर्ट्स (एसेट थ्रैट) के लिए हैमरेस्ट का उपयोग कर रहे हैं और अतिरिक्त टेस्ट लिबास में नहीं खींचना चाहते हैं, तो आप उन SamePropertyValuesAs.samePropertyValuesAsआइटम्स का उपयोग कर सकते हैं जिनके पास ओवरराइड समान पद्धति नहीं है।

उल्टा यह है कि आपको अभी तक एक और परीक्षण ढांचे में खींचने की ज़रूरत नहीं है और जब आप कुछ का उपयोग करते हैं तो expected: field=<value> but was field=<something else>इसके बजाय मुखर विफल ( ) होने पर यह एक उपयोगी त्रुटि देगा ।expected: true but was falseEqualsBuilder.reflectionEquals()

नकारात्मक पक्ष यह है कि यह एक उथली तुलना है और खेतों को छोड़कर के लिए कोई विकल्प नहीं है (जैसे कि इक्वल्सबुर्टल में है), इसलिए आपको नेस्टेड ऑब्जेक्ट्स के आसपास काम करना होगा (जैसे उन्हें हटा दें और स्वतंत्र रूप से तुलना करें)।

सबसे अच्छा मामला:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
assertThat(actual, is(samePropertyValuesAs(expected)));

बदसूरत मामला:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
SomeClass expected = buildExpected(); 
SomeClass actual = sut.doSomething();

assertThat(actual.getSubObject(), is(samePropertyValuesAs(expected.getSubObject())));    
expected.setSubObject(null);
actual.setSubObject(null);

assertThat(actual, is(samePropertyValuesAs(expected)));

तो, अपना जहर उठाओ। अतिरिक्त ढांचा (जैसे यूनिटिल्स), अनलफुल एरर (उदाहरण के बराबर), या उथले तुलना (हैमरेस्ट)।


1
काम के लिए SamePropertyValuesAs आप निर्भरता परियोजना में जोड़ना होगा hamcrest.org/JavaHamcrest/...
bigspawn

मुझे यह समाधान पसंद है, क्योंकि यह एक "पूरी तरह से * अलग अतिरिक्त निर्भरता नहीं जोड़ता है!
घोस्टकैट


2

प्रतिबिंब की तुलना के कुछ तरीके उथले हैं

एक अन्य विकल्प ऑब्जेक्ट को एक जोंस में बदलना और स्ट्रिंग्स की तुलना करना है।

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;    
public static String getJsonString(Object obj) {
 try {
    ObjectMapper objectMapper = new ObjectMapper();
    return bjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
     } catch (JsonProcessingException e) {
        LOGGER.error("Error parsing log entry", e);
        return null;
    }
}
...
assertEquals(getJsonString(MyexpectedObject), getJsonString(MyActualObject))

2

Shazamcrest का उपयोग करना , आप कर सकते हैं:

assertThat(obj1, sameBeanAs(obj2));

हम्क्रेस्ट के बजाय शाजामक्रेस्ट का उपयोग क्यों करें? stackoverflow.com/a/27817702/6648326
मास्टरजोए

1
@ MasterJoe2 मेरे परीक्षणों में, वस्तुओं के अलग-अलग संदर्भ होने पर reflectEqualsवापस लौटता है false
लियोनेल सांचे दा सिल्वा

1

क्षेत्र-दर-क्षेत्र की तुलना करें:

assertNotNull("Object 1 is null", obj1);
assertNotNull("Object 2 is null", obj2);
assertEquals("Field A differs", obj1.getFieldA(), obj2.getFieldA());
assertEquals("Field B differs", obj1.getFieldB(), obj2.getFieldB());
...
assertEquals("Objects are not equal.", obj1, obj2);

1
यह कुछ ऐसा है जो मैं नहीं करना चाहता, क्योंकि एक शुरुआती जोर विफलता नीचे की असफलताओं को छिपाएगी।
रयान नेल्सन

2
क्षमा करें, मुझे आपकी पोस्ट का वह हिस्सा याद आ गया ... एक इकाई-परीक्षण वातावरण में "पूर्ण समानता चित्र" क्यों महत्वपूर्ण है? या तो फ़ील्ड सभी समान हैं (परीक्षण पास), या वे सभी समान नहीं हैं (परीक्षण विफल)।
एथानब

मैं अन्य क्षेत्रों के बराबर नहीं है, तो यह पता लगाने के लिए परीक्षण को फिर से चलाना नहीं चाहता हूं। मैं उन सभी क्षेत्रों को जानना चाहता हूं जो असमान हैं इसलिए मैं उन्हें एक ही बार में संबोधित कर सकता हूं।
रयान नेल्सन

1
एक परीक्षण में कई क्षेत्रों को शामिल करना एक सही 'इकाई' परीक्षण नहीं माना जाएगा। पारंपरिक परीक्षण-संचालित विकास (टीडीडी) के साथ, आप एक छोटा परीक्षण लिखते हैं, और फिर इसे पास करने के लिए केवल पर्याप्त कोड। प्रति क्षेत्र में एक जोर देने से यह करने का सही तरीका है, बस सभी परख को एक परीक्षण में न रखें। आपके द्वारा ध्यान में रखे जाने वाले प्रत्येक क्षेत्र के लिए एक अलग परीक्षा बनाएं। यह आपको सूट के एक ही रन के साथ सभी क्षेत्रों के साथ सभी त्रुटियों को देखने की अनुमति देगा। यदि यह कठिन है, तो इसका मतलब है कि आपका कोड पहली जगह में पर्याप्त रूप से मॉड्यूलर नहीं है और संभवतः इसे एक क्लीनर समाधान में फिर से जोड़ा जा सकता है।
जेसी वेब

यह निश्चित रूप से एक मान्य सुझाव है, और सामान्य तरीका है कि आप एक ही परीक्षण में कई दावे को हल करेंगे। यहाँ एकमात्र चुनौती है, मैं वस्तु के समग्र दृष्टिकोण को पसंद करूँगा। यही है, मैं यह सत्यापित करने के लिए सभी फ़ील्ड एक साथ परीक्षण करना चाहूंगा कि ऑब्जेक्ट एक मान्य स्थिति में है। यह करना मुश्किल नहीं है जब आपके पास एक ओवरराइड समान () विधि होती है (निश्चित रूप से इस उदाहरण में मेरे पास नहीं है)।
रयान नेल्सन

1

AssertJ अभिकथनों का उपयोग #equalsविधि के बिना मूल्यों की तुलना करने के लिए ठीक से ओवरराइड किए जाने के लिए किया जा सकता है, जैसे:

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

// ...

assertThat(actual)
    .usingRecursiveComparison()
    .isEqualTo(expected);

1

चूंकि यह प्रश्न पुराना है, इसलिए मैं JUnit 5 का उपयोग करके एक और आधुनिक दृष्टिकोण सुझाऊंगा।

मुझे यह समाधान पसंद नहीं है क्योंकि मुझे पूर्ण समानता की तस्वीर नहीं मिलती है यदि एक प्रारंभिक मुखर विफल रहता है।

JUnit 5 के साथ, एक विधि है जिसे कहा जाता है Assertions.assertAll()जो आपको अपने परीक्षण में सभी अभिक्रियाओं को एक साथ करने की अनुमति देगा और यह प्रत्येक को निष्पादित करेगा और अंत में किसी भी असफल अभिकथन को आउटपुट करेगा। इसका मतलब यह है कि जो भी दावे पहले विफल होंगे, वे बाद के दावे के निष्पादन को नहीं रोकेंगे।

assertAll("Test obj1 with obj2 equality",
    () -> assertEquals(obj1.getFieldA(), obj2.getFieldA()),
    () -> assertEquals(obj1.getFieldB(), obj2.getFieldB()),
    () -> assertEquals(obj1.getFieldC(), obj2.getFieldC()));

0

आप पूर्ण समानता परीक्षण को "स्वचालित" करने के लिए प्रतिबिंब का उपयोग कर सकते हैं। आप एकल क्षेत्र के लिए लिखे गए समानता "ट्रैकिंग" कोड को लागू कर सकते हैं, फिर ऑब्जेक्ट में सभी क्षेत्रों पर उस परीक्षण को चलाने के लिए प्रतिबिंब का उपयोग करें।


0

यह एक जेनेरिक तुलना विधि है, जो अपने क्षेत्रों के मूल्यों के लिए एक ही वर्ग की दो वस्तुओं की तुलना करती है (ध्यान रखें कि वे प्राप्त करने के लिए सुलभ हैं)

public static <T> void compare(T a, T b) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    AssertionError error = null;
    Class A = a.getClass();
    Class B = a.getClass();
    for (Method mA : A.getDeclaredMethods()) {
        if (mA.getName().startsWith("get")) {
            Method mB = B.getMethod(mA.getName(),null );
            try {
                Assert.assertEquals("Not Matched = ",mA.invoke(a),mB.invoke(b));
            }catch (AssertionError e){
                if(error==null){
                    error = new AssertionError(e);
                }
                else {
                    error.addSuppressed(e);
                }
            }
        }
    }
    if(error!=null){
        throw error ;
    }
}

0

मैं एक बहुत ही मामले पर ठोकर खाई।

मैं एक परीक्षण पर तुलना करने के लिए है कि एक वस्तु एक और एक के रूप में ही विशेषता मान था चाहता था, लेकिन जैसे तरीकों is(), refEq(), आदि मेरी वस्तु अपने में एक शून्य मान होने की तरह कारणों के लिए काम नहीं होगा idविशेषता।

तो यह था समाधान मैंने पाया (ठीक है, एक सहकर्मी पाया):

import static org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare;

assertThat(reflectionCompare(expectedObject, actualObject, new String[]{"fields","to","be","excluded"}), is(0));

यदि प्राप्त मान reflectionCompare0 है, तो इसका मतलब है कि वे समान हैं। यदि यह -1 या 1 है, तो वे कुछ विशेषता पर भिन्न होते हैं।


0

AssertJ के साथ आम मामले में आप कस्टम तुलनित्र रणनीति बना सकते हैं:

assertThat(frodo).usingComparator(raceComparator).isEqualTo(sam)
assertThat(fellowshipOfTheRing).usingElementComparator(raceComparator).contains(sauron);

कथनों में एक कस्टम तुलना रणनीति का उपयोग करना

AssertJ उदाहरण हैं


0

यूनिट एंड्रॉइड ऐप की टेस्टिंग करते समय मेरे पास ठीक वैसा ही कॉंडम था, और सबसे आसान समाधान जो मैं लेकर आया था, वह था कि मैं अपनी वास्तविक और अपेक्षित वैल्यू ऑब्जेक्ट्स को कन्वर्ट करने jsonऔर उन्हें स्ट्रिंग्स के रूप में तुलना करने के लिए Gson का उपयोग करूं

String actual = new Gson().toJson( myObj.getValues() );
String expected = new Gson().toJson( new MyValues(true,1) );

assertEquals(expected, actual);

फ़ील्ड-दर-फ़ील्ड की तुलना करने से इस पर लाभ यह है कि आप अपने सभी फ़ील्ड की तुलना करते हैं, इसलिए भले ही आप बाद में अपनी कक्षा में एक नया फ़ील्ड जोड़ते हैं, यह स्वचालित रूप से परीक्षण किया जाएगा, जैसे कि आप assertEquals()पर एक गुच्छा का उपयोग कर रहे थे यदि आप अपनी कक्षा में अधिक फ़ील्ड जोड़ते हैं, तो सभी फ़ील्ड, जिन्हें तब अपडेट करने की आवश्यकता होगी।

jUnit आपके लिए स्ट्रिंग्स भी प्रदर्शित करता है ताकि आप सीधे देख सकें कि वे कहाँ भिन्न हैं। यह सुनिश्चित नहीं है कि क्षेत्र कितना विश्वसनीय Gsonहै, हालांकि, यह एक संभावित समस्या हो सकती है।


1
फील्ड्स ऑर्डर की गारंटी Gson द्वारा नहीं दी जाती है। आप स्ट्रिंग को JsonParse करना चाहते हैं और पार्सिंग के परिणामस्वरूप JsonElements की तुलना कर सकते हैं
ozma

0

मैंने सभी उत्तरों की कोशिश की और वास्तव में मेरे लिए कुछ भी काम नहीं किया।

तो मैंने अपना एक तरीका बनाया है, जो सरल जाव वस्तुओं की तुलना नेस्टेड संरचनाओं में गहरे जाने के बिना करता है ...

यदि सभी फ़ील्ड मेल नहीं खाते या स्ट्रिंग बेमेल विवरण से मेल खाती है, तो विधि शून्य हो जाती है।

केवल गुण जिनके पास गेटर विधि है, उनकी तुलना की जाती है।

कैसे इस्तेमाल करे

        assertNull(TestUtils.diff(obj1,obj2,ignore_field1, ignore_field2));

बेमेल होने पर नमूना उत्पादन

आउटपुट संपत्ति के नाम और संबंधित वस्तुओं के संबंधित मूल्यों को दर्शाता है

alert_id(1:2), city(Moscow:London)

कोड (जावा 8 और ऊपर):

 public static String diff(Object x1, Object x2, String ... ignored) throws Exception{
        final StringBuilder response = new StringBuilder();
        for (Method m:Arrays.stream(x1.getClass().getMethods()).filter(m->m.getName().startsWith("get")
        && m.getParameterCount()==0).collect(toList())){

            final String field = m.getName().substring(3).toLowerCase();
            if (Arrays.stream(ignored).map(x->x.toLowerCase()).noneMatch(ignoredField->ignoredField.equals(field))){
                Object v1 = m.invoke(x1);
                Object v2 = m.invoke(x2);
                if ( (v1!=null && !v1.equals(v2)) || (v2!=null && !v2.equals(v1))){
                    response.append(field).append("(").append(v1).append(":").append(v2).append(")").append(", ");
                }
            }
        }
        return response.length()==0?null:response.substring(0,response.length()-2);
    }

0

केवल जूनून के लिए एक विकल्प के रूप में, आप मुखरता के बराबर क्षेत्र को शून्य पर सेट कर सकते हैं:

    actual.setCreatedDate(null); // excludes date assertion
    expected.setCreatedDate(null);

    assertEquals(expected, actual);

-1

क्या आप कुछ स्थिर उपयोगिता विधि में पोस्ट किए गए तुलना कोड को डाल सकते हैं?

public static String findDifference(Type obj1, Type obj2) {
    String difference = "";
    if (obj1.getFieldA() == null && obj2.getFieldA() != null
            || !obj1.getFieldA().equals(obj2.getFieldA())) {
        difference += "Difference at field A:" + "obj1 - "
                + obj1.getFieldA() + ", obj2 - " + obj2.getFieldA();
    }
    if (obj1.getFieldB() == null && obj2.getFieldB() != null
            || !obj1.getFieldB().equals(obj2.getFieldB())) {
        difference += "Difference at field B:" + "obj1 - "
                + obj1.getFieldB() + ", obj2 - " + obj2.getFieldB();
        // (...)
    }
    return difference;
}

इस विधि का उपयोग आप इस तरह से JUnit में कर सकते हैं:

अभिकथन ("ऑब्जेक्ट समान नहीं हैं", "", findDifferences (obj1, obj));

जो भद्दा नहीं है और आपको मतभेदों के बारे में पूरी जानकारी देता है, यदि वे मौजूद हैं (assertEqual के सामान्य रूप में बिल्कुल नहीं, लेकिन आपको सभी जानकारी मिलती है तो यह अच्छा होना चाहिए)।


-1

यह ओपी की मदद नहीं करेगा, लेकिन यह किसी भी सी # डेवलपर्स की मदद कर सकता है जो यहां समाप्त होते हैं ...

एनरिक पोस्ट की तरह , आपको बराबर पद्धति को ओवरराइड करना चाहिए।

क्या एक बेहतर प्रैक्टिस है जिसे मैं ऑब्जेक्ट से चाहता हूं, बिना सबक्लासिंग और ओवरराइडिंग बराबरी (ऊग) के बिना?

मेरा सुझाव एक उपवर्ग का उपयोग नहीं करना है। आंशिक वर्ग का उपयोग करें।

आंशिक वर्ग परिभाषाएँ (MSDN)

तो आपका वर्ग ऐसा दिखेगा ...

public partial class TheClass
{
    public override bool Equals(Object obj)
    {
        // your implementation here
    }
}

जावा के लिए, मैं प्रतिबिंब का उपयोग करने के सुझाव से सहमत हूं। बस याद रखें कि आपको जब भी संभव हो प्रतिबिंब का उपयोग करने से बचना चाहिए। यह धीमा है, डिबग करना कठिन है, और भविष्य में बनाए रखने के लिए कठिन भी है क्योंकि आईडीई एक फ़ील्ड का नाम या ऐसा कुछ करके आपके कोड को तोड़ सकता है। सावधान रहे!


-1

आपकी टिप्पणियों से अन्य उत्तरों तक, मुझे समझ में नहीं आता कि आप क्या चाहते हैं।

सिर्फ चर्चा के लिए, हम कहते हैं कि वर्ग ने बराबर पद्धति को ओवरराइड किया।

तो आपका UT कुछ ऐसा दिखेगा:

SomeType expected = // bla
SomeType actual = // bli

Assert.assertEquals(expected, actual). 

और आप कर रहे हैं। इसके अलावा, आप "पूर्ण समानता चित्र" प्राप्त नहीं कर सकते हैं यदि अभिकथन विफल हो जाता है।

जो मैं समझता हूं, आप कह रहे हैं कि भले ही प्रकार ने ओवरराइड किया हो, आप इसमें रुचि नहीं लेंगे, क्योंकि आप "पूर्ण समानता चित्र" प्राप्त करना चाहते हैं। इसलिए बराबरी करने और आगे बढ़ने का कोई मतलब नहीं है।

तो आपके पास विकल्प हैं: या तो संपत्ति की तुलना संपत्ति से करें, प्रतिबिंब या हार्ड-कोडित चेक का उपयोग करके, मैं बाद का सुझाव दूंगा। या: इन वस्तुओं के मानव पठनीय अभ्यावेदन की तुलना करें ।

उदाहरण के लिए, आप एक सहायक वर्ग बना सकते हैं जो उस प्रकार को क्रमबद्ध करता है जो आप किसी XML दस्तावेज़ में करना चाहते हैं और परिणामस्वरूप XML की तुलना करें! इस मामले में, आप नेत्रहीन देख सकते हैं कि वास्तव में क्या समान है और क्या नहीं है।

यह दृष्टिकोण आपको पूरी तस्वीर को देखने का अवसर देगा लेकिन यह भी अपेक्षाकृत बोझिल है (और पहली बार में थोड़ी सी त्रुटि)।


यह संभव है कि मेरा शब्द "पूर्ण समानता चित्र" भ्रामक है। बराबरी लागू करने () वास्तव में समस्या का समाधान होगा। मैं एक ही समय में सभी असमान क्षेत्रों (समानता के लिए प्रासंगिक), डब्ल्यू / ओ को फिर से चलाने के लिए जानने में दिलचस्पी रखता हूं। ऑब्जेक्ट को सीरियल करना एक और संभावना है, लेकिन मुझे जरूरी नहीं कि एक गहरी समान की आवश्यकता है। यदि संभव हो तो मैं संपत्तियों के बराबर () कार्यान्वयन का उपयोग करना चाहूंगा।
रयान नेल्सन

महान! आप पूरी तरह से गुणों के बराबर का उपयोग कर सकते हैं, जैसा कि आपने अपने प्रश्न में कहा था। ऐसा लगता है कि यह इस मामले में सबसे सीधा समाधान है लेकिन जैसा कि आपने उल्लेख किया, कोड बहुत बुरा हो सकता है।
विटालि

-3

आप कक्षा की समान पद्धति को ओवरराइड कर सकते हैं जैसे:

@Override
public int hashCode() {
    int hash = 0;
    hash += (app != null ? app.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    HubRule other = (HubRule) object;

    if (this.app.equals(other.app)) {
        boolean operatorHubList = false;

        if (other.operator != null ? this.operator != null ? this.operator
                .equals(other.operator) : false : true) {
            operatorHubList = true;
        }

        if (operatorHubList) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

यदि आप एक वर्ग से दो ऑब्जेक्ट की तुलना करना चाहते हैं, तो आपको किसी तरह से बराबर और हैश कोड विधि को लागू करना होगा


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