2013-06-14 17 views
6

tôi có các loại sau:Làm thế nào để cấu hình AutoFixture để sử dụng một giá trị enum như hạt giống khi tạo nhiều loại nhất định?

public enum Status 
{ 
    Online, 
    Offline 
} 

public class User 
{ 
    private readonly Status _status; 
    public User(Status status) { _status = status; } 
    public Status Status {get {return _status; }} 
    public string Name {get;set;} 
} 

Bây giờ, khi thực hiện fixture.CreateMany<User> Tôi muốn AutoFixture phải trả lại hai Users, mỗi trạng thái. Tất cả các thuộc tính khác - như Name - phải được lấp đầy bằng dữ liệu ẩn danh.

Câu hỏi:
Cách định cấu hình AutoFixture để thực hiện việc này?


tôi đã cố gắng sau này: bộ sưu tập

  1. Register rằng tin tức lên các đối tượng User:

    fixture.Register(
        () => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s => 
         new User(s))); 
    

    Vấn đề với phương pháp này là AutoFixture không lấp đầy khác các thuộc tính như Name

  2. Customize User sử dụng một nhà máy và đăng ký một bộ sưu tập có sử dụng fixture.Create:

    f.Customize<User>(c => c.FromFactory((Status s) => new User(s))); 
        f.Register(() => 
         Enum.GetValues(typeof(Status)) 
          .Cast<Status>() 
          .Select(s => (User)f.Create(new SeededRequest(typeof(User), s), 
                 new SpecimenContext(f)))); 
    

    đó không làm việc, hoặc. Hạt giống không được sử dụng.

Trả lời

5

Bạn có thể làm điều này:

var users = new Fixture().Create<Generator<User>>(); 

var onlineUser = users.Where(u => u.Status == Status.Online).First(); 
var offlineUser = users.Where(u => u.Status == Status.Offline).First(); 

Nếu bạn đang sử dụng AutoFixture.Xunit, tương đương khai báo là:

[Theory, AutoData] 
public void CreateOneOfEachDeclaratively(Generator<User> users) 
{ 
    var onlineUser = users.Where(u => u.Status == Status.Online).First(); 
    var offlineUser = users.Where(u => u.Status == Status.Offline).First(); 

    // Use onlineUser and offlineUser here... 
} 
+0

Cảm ơn câu trả lời của bạn. Unfortunatelly, không hoạt động nếu thuộc tính 'Status' không phải là' readonly'. 'Đầu tiên'" không bao giờ "trả về (tôi đợi ít nhất 30 giây). –

+0

Từ khóa 'readonly' không liên quan gì đến nó. Tôi vừa xóa từ khóa 'readonly' khỏi repro của mình, và nó không thay đổi kết quả. –

+0

Tôi không nói về trường sao lưu không chỉ đọc được. Tôi đang nói về * tài sản * không phải là chỉ đọc, tức là 'trạng thái Trạng thái công khai {get; bộ; } '. –

3

Bạn có thể khai báo và sử dụng tùy chỉnh, ví dụ: StatusGenerator:

var fixture = new Fixture(); 
fixture.RepeatCount = 2; 
fixture.Customizations.Add(new StatusGenerator()); 

var result = fixture.CreateMany<User>(); 

Một giả thi hành StatusGenerator có thể là như sau:

internal class StatusGenerator : ISpecimenBuilder 
{ 
    private readonly Status[] values; 
    private int i; 

    internal StatusGenerator() 
    { 
     this.values = 
      Enum.GetValues(typeof(Status)).Cast<Status>().ToArray(); 
    } 

    public object Create(object request, ISpecimenContext context) 
    { 
     var pi = request as ParameterInfo; 
     if (pi == null || !pi.ParameterType.IsEnum) 
      return new NoSpecimen(request); 

     return this.values[i == this.values.Length - 1 ? i = 0 : ++i]; 
    } 
} 
+0

Nice, cảm ơn. Nó có thể được mà không cần thiết lập 'RepeatCount'? Theo tôi hiểu, điều này ảnh hưởng đến * tất cả * cuộc gọi đến 'CreateMany', không chỉ cho' Người dùng' ... –

+0

Có, như @MarkSeemann [trả lời] (http://stackoverflow.com/a/17170033/467754):) –

2

Dựa trên Mark's answer, đây là những gì tôi đang sử dụng hiện nay:

fixture.Customize<User>(c => c.Without(x => x.Status)); 
fixture.Customize<IEnumerable<User>>(
    c => 
    c.FromFactory(
     () => Enum.GetValues(typeof(Status)).Cast<Status>() 
        .Select(s => users.First(u => u.Status == s)))); 

fixture.Create<IEnumerable<User>>(); // returns two Users 
2

Tôi biết nó đã được trả lời và Generator là một phát hiện rất thú vị. Tôi nghĩ rằng có một cách tiếp cận đơn giản hơn nhiều cho vấn đề này.

 var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length; 
     var users = fixture.CreateMany<User>(numberOfEnumValues); 

Trong trường hợp hàm tạo phức tạp hơn, với nhiều giá trị Trạng thái hoặc mô hình có trình định thuộc tính của loại Trạng thái. Sau đó, bạn thường có một vấn đề, và máy phát điện có thể thổi là tốt.

Nói rằng:

public class SuperUser : User 
    { 
     public SuperUser(Status status, Status shownStatus): base(status) 
     { 
     } 
    } 

Sau đó, điều này sẽ không bao giờ được đánh giá:

var users = fixture.Create<Generator<SuperUser>>(); 
    var offlineUser = users.Where(u => u.Status == Status.Offline).First(); 
Các vấn đề liên quan