2012-09-14 11 views
23

का उपयोग करने के लिए फोर्स ऑटोफिक्स्चर मेरे पास एकाधिक कन्स्ट्रक्टर के साथ एक डेटा प्रकार है और मुझे लालच (सबसे अधिक पैरामीटर वाले एक) चुनने के लिए ऑटोफिक्चर की आवश्यकता है। डिफॉल्ट व्यवहार कन्स्ट्रक्टर को सबसे छोटी संख्या के साथ चुनना है।लालची कन्स्ट्रक्टर

लेखक का ब्लॉग पोस्ट, http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspx यह प्रतीत नहीं होता है कि इस व्यवहार को ओवरराइड करने का एक तरीका है, तो क्या यह संभव है, और यदि हां, तो कैसे?

उत्तर

26

This is certainly possible

fixture.Customize<MyClass>(c => c.FromFactory(
    new MethodInvoker(
     new GreedyConstructorQuery()))); 

बोर्ड भर में रणनीति बदलने के लिए::

एक ही प्रकार (MyClass) के लिए रणनीति को बदलने के लिए

fixture.Customizations.Add(
    new MethodInvoker(
     new GreedyConstructorQuery())); 

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

public Foo(string name) 
{ 
    this.name = name; 
} 

यह परीक्षण एक अपवाद फेंक देगा:

[Test] 
public void GreedyConstructor() 
{ 
    Fixture fixture = new Fixture(); 
    fixture.Customizations.Add(new MethodInvoker(new GreedyConstructorQuery())); 

    Foo foo = fixture.CreateAnonymous<Foo>(); 
} 

अपवाद है:

Ploeh.AutoFixture.ObjectCreationException: AutoFixture बनाने में असमर्थ रहा System.SByte * से एक उदाहरण, सबसे अधिक संभावना है क्योंकि इसमें कोई सार्वजनिक कन्स्ट्रक्टर नहीं है, यह एक सार या गैर-सार्वजनिक प्रकार है।

तो एसबीटी * के बारे में क्या है? Foo में कोई SByte * नहीं है ...

ठीक है, हाँ वहाँ है। कस्टमाइज़ेशन में MethodInvoker को रखकर, यह सभी स्ट्रिंग के लिए एक सहित डिफ़ॉल्ट निर्माण रणनीतियों को ओवरराइड करता है। इसके बजाय, यह स्ट्रिंग के लिए greediest निर्माता की तलाश में जाता है और जो है:

public String(sbyte* value, int startIndex, int length, Encoding enc); 

और वहाँ sbyte * ...


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

इस तरह एक छोटे से वर्ग लिखें:

public class GreedyEngineParts : DefaultEngineParts 
{ 
    public override IEnumerator<ISpecimenBuilder> GetEnumerator() 
    { 
     var iter = base.GetEnumerator(); 
     while (iter.MoveNext()) 
     { 
      if (iter.Current is MethodInvoker) 
       yield return new MethodInvoker(
        new CompositeMethodQuery(
         new GreedyConstructorQuery(), 
         new FactoryMethodQuery())); 
      else 
       yield return iter.Current; 
     } 
    } 
} 

और इस तरह स्थिरता उदाहरण बनाने के लिए:

Fixture fixture = new Fixture(new GreedyEngineParts()); 

यही काम करना चाहिए

आप क्या कर सकते है।

+0

अच्छा, मुझे यह पसंद है कि आप किसी विशेष प्रकार के व्यवहार को निर्दिष्ट कर सकते हैं।धन्यवाद – RichK

+0

ऑटोफिक्चर वास्तव में ऑब्जेक्ट क्रिएशन अपवाद को फेंक रहा है जब मैं आपके दूसरे उदाहरण का उपयोग करता हूं, संदेश के साथ "ऑटोफिक्चर सिस्टम से एक उदाहरण बनाने में असमर्थ था। बाइट * ..." मेरा डेटा प्रकार बहुत सरल है और निश्चित रूप से बाइट पर निर्भर नहीं है *! क्या यह एक बग है या मैंने ढांचे का दुरुपयोग किया है? – RichK

+0

मैंने अभी कोशिश की है, और सब कुछ आपके पहले उदाहरण – RichK

संबंधित मुद्दे