2012-09-14 25 views
23

Tôi có kiểu dữ liệu với nhiều hàm tạo và tôi cần AutoFixture để chọn tham số nhất (một tham số có nhiều tham số nhất). Hành vi mặc định là chọn hàm tạo với số nhỏ nhất.Bắt buộc AutoFixture để sử dụng hàm tạo tham lam

Bài đăng trên blog của tác giả, http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspx dường như không ngụ ý có cách ghi đè hành vi này, vì vậy có thể thực hiện được không và nếu có thì làm cách nào?

Trả lời

26

This is certainly possible.

Để thay đổi chiến lược cho một loại duy nhất (MyClass):

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

Để thay đổi chiến lược trên mọi lĩnh vực:

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

Khi nó quay ra, tuy nhiên, sử dụng GreedyConstructorQuery trên bảng là rất có thể có vấn đề, như đoạn mã sau đây chứng minh. Hãy tưởng tượng một lớp học với constructor này:

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

Thử nghiệm này sẽ ném một ngoại lệ:

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

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

Trường hợp ngoại lệ ném là:

Ploeh.AutoFixture.ObjectCreationException: AutoFixture đã không thể tạo ra một thể hiện từ System.SByte *, rất có thể vì nó không có hàm tạo công khai, là một kiểu trừu tượng hoặc không công khai.

Vậy điều gì về SByte *? Không có SByte * nào trong Foo ...

Vâng, đúng vậy. Bằng cách đặt MethodInvoker trong Tùy chỉnh, nó ghi đè tất cả chiến lược tạo mặc định, bao gồm cả chiến lược cho chuỗi. Thay vào đó, nó đi tìm kiếm các nhà xây dựng greediest cho chuỗi và đó là:

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

Và có những SByte * ...


Nó vẫn có thể thay sự khiêm tốn thuật toán lựa chọn nhà xây dựng với một thuật toán tham lam, nó chỉ là một chút tham gia hơn tôi lần đầu tiên nhận ra.

gì bạn có thể làm là thế này:

Viết một lớp nhỏ như thế này:

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

và tạo ra các ví dụ Lịch thi đấu như thế này:

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

Điều đó sẽ làm việc.

+0

Tốt, tôi thích rằng bạn có thể chỉ định hành vi cho một loại cụ thể.Cảm ơn – RichK

+0

AutoFixture là thực sự ném một ObjectCreationException khi tôi sử dụng ví dụ thứ hai của bạn, với thông báo "AutoFixture đã không thể tạo một thể hiện từ System.SByte * ..." Kiểu dữ liệu của tôi rất đơn giản và chắc chắn không phụ thuộc vào một byte *! Đây có phải là lỗi hoặc tôi đã sử dụng sai khung này không? – RichK

+0

Tôi vừa thử và mọi thứ hoạt động tốt bằng ví dụ đầu tiên của bạn – RichK

Các vấn đề liên quan