2013-03-29 18 views
11

ストレージ用のEntity Frameworkを持つMVC4プロジェクトがあります。 私たちのテストでは、最近Autofixtureを使い始めました。本当に素晴らしいです。仮想プロパティを無視します

当社のモデルグラフが非常に深いであり、通常AutoFixtureで一つのオブジェクトを作成すると、グラフ全体を作成します。人 - >チーム - >部門 - >会社 - >契約 - > ....など

この問題は時間です。 オブジェクトの作成には最大で1秒かかります。そして、これはテストが遅くなる。私は自分自身が多くのことをやって見つける何

はこのようなものです:

 var contract = fixture.Build<PersonContract>() 
      .Without(c => c.Person) 
      .Without(c => c.PersonContractTemplate) 
      .Without(c => c.Occupation) 
      .Without(c => c.EmploymentCompany) 
      .Create<PersonContract>(); 

そして、これは動作し、それが迅速です。しかし、この過剰仕様はテストを読みにくくし、時には重要ではない.Without()のリストに.With(c => c.PersonId, 42)のような重要な情報を失います。

これらの無視されたオブジェクトはすべて、Entity Frameworkのナビゲーションプロパティであり、すべて仮想です。

仮想メンバーを無視するようにAutoFixtureに指示するグローバルな方法はありますか?

私はISpecimentBuilderを作成しようとしたが、ない運:私たちが構築され、そのオブジェクトを検出するために、ISpecimenBuilderに方法を見つけるように見えることはできません

public class IgnoreVirtualMembers : ISpecimenBuilder 
{ 
    public object Create(object request, ISpecimenContext context) 
    { 

     if (request.GetType().IsVirtual // ?? this does not exist) 
     { 
      return null; 
     } 
    } 
} 

が別のクラスでの仮想メンバーではありません。おそらくISpecimenBuilderこれはこれを行うのに適切な場所ではありません。他のアイデア?

答えて

20

私は私が欲しいものを行うための方法を発見したマルコのブログ(this particularly)上でより多くのビットを読む

/// <summary> 
/// Customisation to ignore the virtual members in the class - helps ignoring the navigational 
/// properties and makes it quicker to generate objects when you don't care about these 
/// </summary> 
public class IgnoreVirtualMembers : ISpecimenBuilder 
{ 
    public object Create(object request, ISpecimenContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 

     var pi = request as PropertyInfo; 
     if (pi == null) 
     { 
      return new NoSpecimen(request); 
     } 

     if (pi.GetGetMethod().IsVirtual) 
     { 
      return null; 
     } 
     return new NoSpecimen(request); 
    } 
} 
そして、あなたがカスタマイズにこれらをラップすることができます。

public class IgnoreVirtualMembersCustomisation : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customizations.Add(new IgnoreVirtualMembers()); 
    } 
} 

だからあなたのテストであなたは次のようにします:

var fixture = new Fixture().Customize(new IgnoreVirtualMembersCustomisation()); 

あなたの複雑なモデルを作成してください。

お楽しみください!

+0

保存日。しかし、少なくとも米国ではCustomisationsのスペルがカスタマイズされています。 :) –

+5

私は知っている、厄介なzはすべての* sationsになる。英国では、 "s" - )))) – trailmax

+0

これは素晴らしい解決策です。私はクラスを自分のプロジェクトにドロップしてすぐにMoqと一緒に使っていました。よくできました! – Halcyon

3

私はこの同じ問題を抱え、さらに一歩進んで、遅延ロードナビゲーションプロパティのカスタマイズを作成することに決めました。プロジェクトはGithubNuGetです。タイプFooのオブジェクトを作成しますvar foo = fixture.Create<Foo>()を呼び出して、このカスタマイズで

class Foo 
{ 
    public int Id { get; set; } 
    public int BarId { get; set; } 
    public virtual Bar Bar { get; set; } 
} 

class Bar 
{ 
    public int Id { get; set; } 
    public int FooId { get; set; } 
    public virtual Foo Foo { get; set; } 
} 

は、循環依存があり、それ以下の単純なオブジェクトグラフを考えてみましょう。 foo.Barゲッターを呼び出すと、DynamicProxyとAutoFixtureを使用して、その場で Barのインスタンスを作成し、それをそのプロパティに割り当てます。その後の foo.Barの呼び出しは、同じオブジェクトを返します。

N.B.カスタマイズは十分にスマートではありませんfoo.Bar.Foo = foo - これは必要に応じて手動で行う必要があります

+0

それは素晴らしいです!ありがとうございました! – trailmax

+0

@AlexFoxGill、あなたのプロジェクトはもはや最新のAutoFixture 3.3+と互換性がありません。カスタマイズしてUTを実行しようとすると、アセンブリが正しくないというエラーが生成されます。 – Encryption

+0

@Ancryptionありがとうございました – AlexFoxGill

関連する問題