2012-09-14 17 views
23

Birden fazla kurucuya sahip bir veri tipim var ve en hızlı olanı seçmek için Otomatik Düzeltme'ye ihtiyacım var (en çok parametre içeren). Varsayılan davranış, kurucuyu en küçük sayı ile seçmek.Zorlu AutoFixture'ı greediest kurucu kullanmak için zorlayın

Yazarın blog yazısı, http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspx bu davranışı geçersiz kılmanın bir yolu olduğunu ima etmiyor gibi görünüyor, bu mümkün mü ve eğer öyleyse, nasıl?

cevap

26

This is certainly possible. Sonradan anlaşıldı ki GreedyConstructorQuery kullanarak Ancak

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

:

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

yönüyle stratejisini değiştirmek için:

tek tip ( MyClass) için stratejisini değiştirmek için Aşağıdaki kod parçacığının gösterdiği gibi, tahta boyunca büyük olasılıkla sorunludur. Bu yapıcı bir sınıf düşünün:

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

Bu test bir istisna durumu:

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

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

atılan istisnadır:

Ploeh.AutoFixture.ObjectCreationException: AutoFixture oluşturamadı System.SByte * 'dan bir örnek, büyük olasılıkla kamu kurucusu olmadığı için soyut veya kamuya açık olmayan bir türdür.

Peki SByte hakkında ne var? Foo ...

'de SByte * yok, evet var. MethodInvoker'ı Özelleştirme içine yerleştirerek, dizeler için bir tane de dahil olmak üzere tüm varsayılan oluşturma stratejilerini geçersiz kılar. Bunun yerine, dize için açgözlü yapıcı aramaya devam ediyor ve şudur:

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

Ve O hala mümkün sbyte * ...


mütevazı yapıcı seçim algoritması ile değiştirin var açgözlü bir algoritma, ilk fark ettiğimden biraz daha fazla.

bunun gibi küçük sınıf yaz:

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; 
     } 
    } 
} 

ve bunun gibi Armatür örneğini oluşturun:

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

çalışması gerekir

Ne yapabilirsiniz budur.

+0

Güzel, belirli bir tür için davranış belirtebilirsiniz.Teşekkürler – RichK

+0

AutoFixture aslında ikinci örneğinizi kullandığınızda bir ObjectCreationException atıyor, "AutoFixture System.SByte * 'den bir örnek oluşturamadı ..." Veri türüm çok basit ve kesinlikle bir bayta bağlı değil *! Bu bir hata mı yoksa çerçeveyi yanlış mı kullandım? – RichK

+0

Sadece denedim ve her şey ilk örneğinizi kullanarak iyi çalışıyor – RichK

İlgili konular