2013-10-10 35 views
6

Tôi muốn tạo danh sách các đối tượng tùy chỉnh sử dụng AutoFixture. Tôi muốn các đối tượng N đầu tiên có thuộc tính được đặt thành một giá trị và phần còn lại sẽ được đặt thành giá trị khác (hoặc đơn giản được đặt theo chiến lược mặc định của Fixture).Làm cách nào để chỉ định thuộc tính cho một mục con trong một danh sách?

Tôi biết rằng tôi có thể sử dụng Fixture.CreateMany<T>.With, nhưng điều này áp dụng một hàm cho tất cả thành viên của danh sách.

Trong NBuilder có các phương pháp có tên TheFirstTheNext (trong số những người khác) cung cấp chức năng này. Một ví dụ về việc sử dụng chúng:

Cho một lớp Foo:

class Foo 
{ 
    public string Bar {get; set;} 
    public int Blub {get; set;} 
} 

người ta có thể nhanh chóng một loạt các Foo giống như vậy:

class TestSomethingUsingFoo 
{ 
    /// ... set up etc. 

    [Test] 
    public static void TestTheFooUser() 
    { 
     var foosToSupplyToTheSUT = Builder<Foo>.CreateListOfSize(10) 
      .TheFirst(5) 
       .With(foo => foo.Bar = "Baz") 
      .TheNext(3) 
       .With(foo => foo.Bar = "Qux") 
      .All() 
       .With(foo => foo.Blub = 11) 
      .Build(); 

     /// ... perform the test on the SUT 
    } 
} 

này đưa ra một danh sách các đối tượng thuộc loại Foo với các thuộc tính sau:

[Object] Foo.Bar Foo.Blub 
-------------------------------- 
0   Baz  10 
1   Baz  10 
2   Baz  10 
3   Baz  10 
4   Baz  10 
5   Qux  10 
6   Qux  10 
7   Qux  10 
8   Bar9  10 
9   Bar10  10 

(Các giá trị Bar9Bar10 đại diện cho sơ đồ đặt tên mặc định của NBuilder)

Có cách nào tích hợp để đạt được điều này bằng cách sử dụng AutoFixture? Hoặc một cách thành ngữ để thiết lập một vật cố để hành xử như thế này?

+0

Lớp học 'Foo' trông như thế nào? –

+0

@MarkSeemann Tôi đã mở rộng ví dụ bằng cách sử dụng 'Foo' để làm cho nó rõ ràng hơn một chút. Nếu bạn có nghĩa là lớp thực tế trong dự án thực tế của tôi mà 'Foo' là một proxy, nó giống nhau: chỉ là một POCO với các trường' string', 'int',' DateTime' có thể đặt/có thể cài đặt. – Peter

Trả lời

10

By xa cách dễ nhất để làm điều đó sẽ là như thế này:

var foos = fixture.CreateMany<Foo>(10).ToList(); 
foos.Take(5).ToList().ForEach(f => f.Bar = "Baz"); 
foos.Skip(5).Take(3).ToList().ForEach(f => f.Bar = "Qux"); 
foos.ForEach(f => f.Blub = 11); 

Gán giá trị cho các thuộc tính đã được tích hợp sẵn trong C#, vì vậy thay vì cung cấp một API hạn chế mà không thể nào cho phép bạn để làm mọi thứ bạn muốn làm, the AutoFixture philosophy is to use the language constructs already available.

Bước triết học tiếp theo là nếu bạn thường cần làm điều gì đó như vậy, thì SUT có thể có lợi từ việc thiết kế lại.

+0

Vâng, đó là chiến lược tôi đã sử dụng. Tôi nhận ra từ các cuộc thảo luận tại liên kết của bạn rằng trường hợp sử dụng này phân kỳ từ ý định cốt lõi của AutoFixture. Tôi vừa quen với đường cú pháp ngon của NBuilder ... đường mà tôi nghi ngờ tôi có thể tự mình thực hiện trên đầu trang của 'IEnumerable ' nếu tôi thực sự muốn cảm thấy 'thông thạo' đó đối với mã của mình. – Peter

+1

Giải pháp gọn gàng. IMHO, tôi vẫn nghĩ rằng nó sẽ được tốt đẹp nếu điều này được xây dựng trong. – Phil

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