2013-06-14 4 views
6

私は次の種類があります。特定のタイプの多くを作成するときに、列挙型の値をシードとして使用するようにAutoFixtureを設定するにはどうすればよいですか?

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

fixture.CreateMany<User>を実行するとき、私はAutoFixtureは、状態ごとに1つずつ2 Usersを返すようにしたいです。 Nameのような他のすべてのプロパティは、匿名データで埋めなければなりません。

質問:
これを行うにはAutoFixtureを設定するにはどうすればよいですか?


は、私は、次のこの試みた:

  1. 登録コレクションをそのUserオブジェクトニュースアップ:

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

    このアプローチの問題はAutoFixtureが他方を満たしていないということです特性は次のとおりです。Name

  2. カスタマイズUserファクトリを使用して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)))); 
    

    どちらか動作しませんでした。種子は使用されていません。

答えて

5

あなたがこれを行うことができます:あなたはAutoFixture.Xunitを使用している場合

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(); 

を、宣言的な同等物は次のとおりです:

[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

あなたの答えをありがとう。 Unfortunatellyは、 'Status'プロパティが' readonly'でない場合には動作しません。 「最初に」「決して」戻ってこない(私は少なくとも30秒待った)。 –

+0

'readonly'キーワードはそれとは関係ありません。私は私のreproから 'readonly'キーワードを削除しましたが、結果は変更されませんでした。 –

+0

私は裏書きフィールドが読み込み専用ではないと言っているわけではありません。私は*プロパティ*については読んでいない、つまり 'public Status Status {get;セット; } '。 –

3

カスタマイズを宣言して使用することができます。 StatusGenerator

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

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

StatusGenerator架空の実装は、次のことができます:

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

ニース、おかげで

があると言います。 'RepeatCount'を設定しなくても可能でしょうか?私が理解しているように、これは 'User'のものだけでなく、' CreateMany'へのすべての呼び出しに影響します... –

+0

はい、@MarkSeemannとして(http://stackoverflow.com/a/17170033/467754): ) –

2

Mark's answerに基づいて、これは私が今使っているものです:

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

私はそれが既に回答されて知っているとジェネレータは非常に興味深い発見しました。 私は、この問題のはるかに簡単なアプローチがあると思います。

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

コンストラクタがより複雑で複数のステータス値を持つ場合、またはモデルにステータスタイプのプロパティ設定子がある場合。その後、一般的に問題があり、発電機も吹くことがあります。

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

が、これは評価されることはありません:

var users = fixture.Create<Generator<SuperUser>>(); 
    var offlineUser = users.Where(u => u.Status == Status.Offline).First(); 
関連する問題