2008-10-25 10 views
29

मैं नुनिट टेस्ट के साथ सी # 2.0 का उपयोग कर रहा हूं। मेरे पास कुछ वस्तु है जिसे क्रमबद्ध करने की आवश्यकता है। ये वस्तुएं काफी जटिल हैं (विभिन्न स्तरों पर विरासत और इसमें कई वस्तुएं, घटनाएं और प्रतिनिधि शामिल हैं)।मेरी ऑब्जेक्ट वास्तव में धारावाहिक होने पर इकाई परीक्षण कैसे करें?

यह सुनिश्चित करने के लिए कि मेरा ऑब्जेक्ट सुरक्षित रूप से क्रमबद्ध है, मैं यूनिट टेस्ट कैसे बना सकता हूं?

उत्तर

13

मैं काम पर यहाँ कुछ इकाई परीक्षण में यह है:

MyComplexObject dto = new MyComplexObject(); 
MemoryStream mem = new MemoryStream(); 
BinaryFormatter b = new BinaryFormatter(); 
try 
{ 
    b.Serialize(mem, dto); 
} 
catch (Exception ex) 
{ 
    Assert.Fail(ex.Message); 
} 

आपकी मदद कर सकता है ... शायद अन्य विधि बेहतर हो सकता है लेकिन यह एक अच्छी तरह से काम करता है।

+0

हालांकि आपको गैर-क्रमबद्ध (या जावा में क्षणिक) वस्तुओं से सावधान रहना होगा, और उनको आपके क्रमिकरण और deserialization के हिस्से के रूप में परीक्षण किया जाना चाहिए। – Egwor

+0

@Egwor कोई nonSerialized वस्तुओं, केवल nonSerialized क्षेत्रों हैं। – Mishax

13

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

3

serialize वस्तु (स्मृति या डिस्क के लिए), यह deserialize, उपयोग प्रतिबिंब फिर

इस मानता है कि (बेशक क्रमबद्धता को छोड़कर) दो, तो रन तुलना करने के लिए उस वस्तु के लिए इकाई परीक्षण के सभी अपने इकाई परीक्षण एक लक्ष्य के रूप एक वस्तु स्वीकार कर सकते हैं के बजाय बनाने के लिए अपने स्वयं

+0

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

+1

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

40

यहाँ एक सामान्य तरीका है:

public static Stream Serialize(object source) 
{ 
    IFormatter formatter = new BinaryFormatter(); 
    Stream stream = new MemoryStream(); 
    formatter.Serialize(stream, source); 
    return stream; 
} 

public static T Deserialize<T>(Stream stream) 
{ 
    IFormatter formatter = new BinaryFormatter(); 
    stream.Position = 0; 
    return (T)formatter.Deserialize(stream); 
} 

public static T Clone<T>(object source) 
{ 
    return Deserialize<T>(Serialize(source)); 
} 
+0

पूरी तरह से काम करता है। क्लोन कॉपी में मूल की तुलना करना क्रमबद्धता का एक बड़ा परीक्षण है क्योंकि IsSerializable केवल वर्ग की विशेषता की जांच करता है, न कि बेस क्लास या अन्य गुण – Catch22

+1

कृपया, टाइपो को सही करें और मैं अपना वोट दूंगा। :) – jpbochi

+0

यदि आप क्लोन विधि के हस्ताक्षर को 'सार्वजनिक स्थैतिक टी क्लोन (टी स्रोत) में बदलते हैं, तो आपको मुफ्त में उचित प्रकार का अनुमान मिलता है। – fabsenet

2

यहाँ एक समाधान है कि रिकर्सिवली कि ओब की जाँच करने के IsSerializable का उपयोग करता है जेक्ट और इसकी सभी गुण Serializable हैं।

private static void AssertThatTypeAndPropertiesAreSerializable(Type type) 
    { 
     // base case 
     if (type.IsValueType || type == typeof(string)) return; 

     Assert.IsTrue(type.IsSerializable, type + " must be marked [Serializable]"); 

     foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) 
     { 
      if (propertyInfo.PropertyType.IsGenericType) 
      { 
       foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments()) 
       { 
        if (genericArgument == type) continue; // base case for circularly referenced properties 
        AssertThatTypeAndPropertiesAreSerializable(genericArgument); 
       } 
      } 
      else if (propertyInfo.GetType() != type) // base case for circularly referenced properties 
       AssertThatTypeAndPropertiesAreSerializable(propertyInfo.PropertyType); 
     } 
    } 
+0

सामान्य तर्कों को किसी प्रकार के लिए क्रमबद्ध करने की आवश्यकता नहीं है, उदाहरण के लिए 'ऑब्जेक्ट कॉम्पैडर 'serializable है। – erikkallen

1

दुर्भाग्यवश, आप वास्तव में इसके लिए परीक्षण नहीं कर सकते हैं। इस मामले की कल्पना कीजिए:

[Serializable] 
class Foo { 
    public Bar MyBar { get; set; } 
} 

[Serializable] 
class Bar { 
    int x; 
} 

class DerivedBar : Bar { 
} 

public void TestSerializeFoo() { 
    Serialize(new Foo()); // OK 
    Serialize(new Foo() { MyBar = new Bar() }; // OK 
    Serialize(new Foo() { MyBar = new DerivedBar() }; // Boom 
} 
+0

आप 'MyBar' को' DerivedBar' कैसे असाइन कर सकते हैं? – Default

+1

टाइपो। फिक्स्ड ..... – erikkallen

0

शायद थोड़ा दिन में देर से, लेकिन अगर आप FluentAssertions पुस्तकालय का उपयोग कर रहे हैं, तो यह एक्सएमएल क्रमबद्धता, द्विआधारी क्रमांकन, और डेटा अनुबंध क्रमबद्धता के लिए कस्टम कथनों है।

theObject.Should().BeXmlSerializable(); 
theObject.Should().BeBinarySerializable(); 
theObject.Should().BeDataContractSerializable(); 

theObject.Should().BeBinarySerializable<MyClass>(
    options => options.Excluding(s => s.SomeNonSerializableProperty)); 
संबंधित मुद्दे