12

हमने एक परीक्षण लिखा है जो निम्न जैसा दिखता है। इस परीक्षण की आवश्यकता है कि हम CodeTableItem श्रेणी के लिए एन Equal -overload बनाया है:[ऑटोफिक्स्चर] सेमेन्टिक कॉम्परिसन का चयन अनुक्रम/संग्रह/सरणी/आईनेमेरेबल

ICollection<CodeTableItem> expectedValutaList = new List<CodeTableItem>(); 
expectedValutaList.Add(new CodeTableItem("DKK", "DKK")); 
expectedValutaList.Add(new CodeTableItem("EUR", "EUR")); 
RepoDac target = new RepoDac(); 

var actual = target.GetValutaKd(); 

CollectionAssert.AreEqual(expectedValutaList.ToList(),actual.ToList()); 

परीक्षण ठीक काम करता है, लेकिन Equality समारोह को दुर्भाग्यपूर्ण निर्भरता है, जिसका अर्थ है कि अगर मैं एक के साथ CodeTableItem श्रेणी का विस्तार अधिक फ़ील्ड, और Equals -फंक्शन का विस्तार करना भूल जाता है, यूनिट परीक्षण अभी भी हरा चलाता है, हालांकि हम सभी क्षेत्रों के लिए परीक्षण नहीं करते हैं। हम इस Equality प्रदूषण से बचना चाहते हैं (Test Specific Equality देखें), जिसे केवल परीक्षण के अनुरूप लिखा गया है।

हम OfLikeness उपयोग करने की कोशिश की है, और इस तरह से परीक्षण फिर से लिखा है:

ICollection<CodeTableItem> expectedValutaList = new List<CodeTableItem>(); 
expectedValutaList.Add(new CodeTableItem("DKK", "DKK")); 
expectedValutaList.Add(new CodeTableItem("EUR", "EUR")); 
var expectedValutaListWithLikeness = 
      expectedValutaList.AsSource().OfLikeness<List<CodeTableItem>>(); 

RepoDac target = new RepoDac(); 
ICollection<CodeTableItem> actual; 

actual = target.GetValutaKd(); 

expectedValutaListWithLikeness.ShouldEqual(actual.ToList()); 

लेकिन परीक्षण में विफल रहता है क्योंकि Capacity बराबर नहीं है। मैंने कोड लिखा है जो कई बार प्रतिबिंब के माध्यम से चलता है, और आमतौर पर फ़ील्ड को अनदेखा करने के लिए ओवरलोड को कार्यान्वित करता है। क्या OfLikeness या ShouldEqual के साथ कुछ फ़ील्ड को अनदेखा करने का कोई तरीका है? या इस मुद्दे को हल करने का कोई और तरीका है?

उत्तर

8

बस .Without(x => x.Capacity) जोड़ें और मूल्यों की तुलना करते समय Likeness उदाहरण Capacity संपत्ति को अनदेखा कर देगा।

var expectedValutaListWithLikeness = 
     expectedValutaList.AsSource().OfLikeness<List<CodeTableItem>>() 
     .Without(x => x.Capacity); 

अद्यतन:

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

यह मानते हुए कि RepoDac वर्ग की तरह कुछ देता है:

public class RepoDac 
{ 
    public ICollection<CodeTableItem> GetValutaKd() 
    { 
     return new[] 
     { 
      new CodeTableItem("DKK", "DKK"), 
      new CodeTableItem("EUR", "EUR") 
     }; 
    } 
} 

expectedValutaList पर प्रत्येक उदाहरण आप एक गतिशील प्रॉक्सी कि ओवरराइड करता है बना सकते हैं के लिए समानता का उपयोग कर बराबर है:

var object1 = new CodeTableItem("DKK", "DKK1") 
    .AsSource().OfLikeness<CodeTableItem>() 
    .Without(x => x.Property2) 
    .CreateProxy(); 

var object2 = new CodeTableItem("EUR2", "EUR") 
    .AsSource().OfLikeness<CodeTableItem>() 
    .Without(x => x.Property1) 
    .CreateProxy(); 

सूचना कैसे ऑब्जेक्ट 1 और ऑब्जेक्ट 2 में भी गतिशील रूप से जेनरेट किए गए समान हैं। (प्रथम Property2 पर ध्यान नहीं देता है, जबकि दूसरा ध्यान नहीं देता Property1।)

परीक्षण नीचे से गुजरता है:

var expected = new List<CodeTableItem>(); 
expected.Add(object1); 
expected.Add(object2); 

var target = new RepoDac(); 
var actual = target.GetValutaKd(); 

Assert.IsTrue(expected.SequenceEqual(actual)); 

नोट:

यह expected उदाहरण के साथ शुरू करने के लिए आवश्यक है जो गतिशील रूप से जेनरेट की गई प्रॉक्सी (बराबर ओवरराइडिंग) शामिल है।

आपको इस सुविधा here पर अधिक जानकारी मिल सकती है।

12

क्यों आपको लगता है कि

मैं किसी भी List<T> से जब एक स्वरूप बनाने नहीं लगता कि जैसे यह करने के लिए नहीं करना चाहती है कि तुम क्या करना चाहते हैं करता है। जैसा कि मैं समझता हूं, आप दो सूचियों के सामग्री की तुलना करना चाहते हैं। यह दो सूचियों की तुलना करने जैसा नहीं है ...

विचार करें कि लिकनेस क्या करता है: यह संपत्ति मानों की तुलना करता है। List<T> के गुण क्या हैं?

वे

  • क्षमता
  • गणना

निकोस Baxevanis उसके जवाब में बताते हैं के रूप में, आप विधि के बिना क्षमता संपत्ति के मूल्य की अनदेखी करने के लिए उपयोग कर सकते हैं, लेकिन यह है कि साधन कि केवल गणना संपत्ति बनी हुई है।

दूसरे शब्दों में, अगर तुमने किया था कि, इस:

expectedValutaListWithLikeness.ShouldEqual(actual.ToList()); 

कार्यात्मक इस के बराबर होगा:

Assert.AreEqual(expected.Count, actual.Count) 

दूसरे शब्दों में, सूचियों पूरी तरह से अलग डेटा हो सकता था, लेकिन परीक्षण अभी भी पास होगा यदि केवल प्रत्येक सूची में तत्वों की एक ही मात्रा है। यही कारण है कि शायद तुम क्या चाहते नहीं है ...

आपको क्या करना चाहिए

आप एक दूसरे के खिलाफ प्रत्येक तत्व तुलना करने के लिए समानता का उपयोग कर सकते हैं। कुछ इस तरह काम करना चाहिए:

var expectedValutaList = new List<CodeTableItem>(); 
expectedValutaList.Add(new CodeTableItem("DKK", "DKK")); 
expectedValutaList.Add(new CodeTableItem("EUR", "EUR")); 

var expectedValutaListWithLikeness = from cti in expectedValutaList 
            select cti 
             .AsSource() 
             .OfLikeness<CodeTableItem>(); 

var target = new RepoDac(); 

var actual = target.GetValutaKd(); 

Assert.IsTrue(expectedValutaListWithLikeness.Cast<object>().SequenceEqual(
    actual.Cast<object>())); 

तुम भी दावे के लिए CollectionAssert उपयोग करने में सक्षम हो सकता है, लेकिन यह इतने सालों के बाद से मैं पिछले इस्तेमाल किया MSTest कि मुझे लगता है कि विधि का quirks याद नहीं कर सकते हो गया है ...

+0

बहुत बहुत धन्यवाद, मार्क, उसने ऐसा किया! सुरुचिपूर्ण! –

3

निम्नलिखित जवाब me asking myself a duplicate of this question से उत्पन्न हुआ,

नीचे

आप एक SequenceLike आपरेशन जो LINQ के SequenceEqual ऑपरेटर की ओर संकेत इस्तेमाल कर सकते हैं देखते हैं।

[Theory, AutoData] 
public void ShouldMap( Dto inputDto) 
{ 
    var mapped = inputDto.ToModel(); 

    inputDto.AsSource().OfLikeness<Model>() 
     .Without(x => x.IgnorableProperty) 
     .With(x => x.Tags).EqualsWhen((dto, model) => 
      model.Tags.SequenceLike(dto.Tags)) 
     .ShouldEqual(mapped); 
} 

ऑल-इन-एक सहायक @Nikos Baxevanis से उत्साह को @Mark सीनैन का जवाब धन्यवाद के आधार पर की चमकदार कम कार्यान्वयन: - -:

static class LikenessSequenceExtensions 
{ 
    public static bool SequenceLike<T, TSource>(this IEnumerable<T> that, IEnumerable<TSource> source) 
    { 
     return SequenceLike<T, TSource>(that, source, x => x); 
    } 

    public static bool SequenceLike<T, TSource>(this IEnumerable<T> that, IEnumerable<TSource> source, Func<Likeness<TSource, T>, IEquatable<T>> customizeLikeness) 
    { 
     return source.Select(x => customizeLikeness(x.AsSource().OfLikeness<T>())).SequenceEqual(that.Cast<object>()); 
    } 
} 

यह एक लिखने की अनुमति देता

मेरी मूल कार्यान्वयन:

static class LikenessSequenceExtensions0 
{ 
    public static bool SequenceLike0<T, TSource>(this T[] that, TSource[] source) 
    { 
     return source.SequenceLike0(that, likeness => likeness); 
    } 

    public static bool SequenceLike0<T, TSource>(this T[] that, TSource[] source, Func<Likeness<TSource, T>, IEquatable<T>> customizeLikeness) 
    { 
     return source.SequenceEqual(that, (x, y) => customizeLikeness(x.AsSource().OfLikeness<T>()).Equals(y)); 
    } 

    public static bool SequenceEqual<T, TSource>(this T[] that, TSource[] source, Func<T, TSource, bool> equals) 
    { 
     return that.Length == source.Length && that.Zip(source, Tuple.Create).All(x => equals(x.Item1, x.Item2)); 
    } 
} 

मूल डुप्लिकेट प्रश्न

मैं अपने xunit.AutoFixture आधारित परीक्षणों में/सरणियों के लिए Test Specific EqualityIEnumerable<T>/seq<'T> प्रबंधन करने के लिए स्पष्ट तरीका के लिए देख रहा हूँ।

ओओटीबी (मैंने यह पता खो दिया है कि मैंने इसे कहाँ सीखा), Ploeh.SemanticComparison के Likeness संस्करण केवल व्यक्तिगत वस्तुओं पर 2.12 कार्यों तक काम करते हैं।

वस्तुओं के संग्रह (आदर्श ओओटीबी लेकिन विस्तार विधियों के सुव्यवस्थित सूट के लिए बहुत खुले) के लिए एक ही तकनीक को लागू करने का सबसे अच्छा तरीका क्या है जिसमें एम्बेडेड ऑब्जेक्ट्स को एक संगत तरीके से शामिल करने वाली वस्तुओं की समानता व्यक्त करने में मदद मिलती है?

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

+0

ग्रेट कोड ... धन्यवाद! – AxelEckenberger

3

से जवाब संभव है की सूक्ष्मता के साथ हैरान कर दिया गया है मैं इस इस समस्या हो रही दूसरों के लिए स्पष्ट बनाना चाहते थे। छुट्टियां, दोनों की तुलना को अनुकूलित करते समय:

var expectedCalendar = newCalendar.AsSource() 
    .OfLikeness<Calendar>() 
    .Without(c=>c.Id) //guid, will never be equal 
    .With(c=>c.Holidays).EqualsWhen((source, dest) => 
     source.Holidays.SequenceLike(dest.Holidays, holiday => 
      holiday.Without(h=>h.SecondsUntil) //changes every second 
    )); 

इस उदाहरण में, आप पहले कैलेंडर ऑब्जेक्ट पर बहिष्कृत करने के लिए गुण सेट अप करते हैं। फिर आप छुट्टियों के संग्रह को संभालने के लिए कार्यान्वयन के साथ एक कस्टम बराबर देते हैं। अवकाश => लैम्ब्डा तब आपको माता-पिता की तरह बाल तुलना को अनुकूलित करने की अनुमति देता है। आप घोंसले को तब तक जारी रख सकते हैं जब आप बहुत सारे ब्रांड्स का आनंद लेते हैं।

+0

+1 अच्छा। और हे, उन दोस्ताना गले लगाने वाले कोष्ठक बहुत ही आरामदायक हैं :) –

0

मुझे यकीन है कि अगर यह सवाल अब भी प्रासंगिक है नहीं कर रहा हूँ, लेकिन क्या आप देख रहे हैं https://github.com/jmansar/SemanticComparisonExtensions

है आप संग्रह तुलना करने के लिए .WithCollectionInnerLikeness() का उपयोग कर सकते हैं और यह आप क्या चाहते हैं आप मिल जाएगा।