2015-11-13 5 views
5
のインタフェースと実装の両方を注入

は、次のクラスを考えてみましょう:はAutoFixture

public interface IInterface {} 
public class Class : IInterface {} 

public class Customization : ICustomization 
{ 
    readonly IInterface item; 

    public Customization() : this(new Class()) {} 

    public Customization(IInterface item) 
    { 
     this.item = item; 
    } 

    public void Customize(IFixture fixture) 
    { 
     fixture.Inject(item); 
     var created = fixture.Create<Class>(); // Would like this to resolve as item from previous line. 
    } 
} 

私はに実行している問題はClassではないのに対しIInterfaceが、注入されていることです。両方とも同じインスタンスが返されるようにIInterfaceClassの両方を注入する方法はありますか?

私はテストメソッドの属性とICustomization(またはICustomization内)を使用して、これを実行したいとしないことに注意してください。私はこれらの2つのクラスでカスタマイズされたインジェクションを行うつもりです。 [Frozen(Matching.ImplementedInterfaces)]Class itemをパラメータとして使用すると、凍結されたクラスがICustomization.Customizeメソッドの注入された値を上書きするため、機能しません。

は、さらに、これはサンプルコードがあると私はそれを使用していないかということに注意してください。 xUnitの試験方法では、私は上記の凍結IInstanceするパラメータとして指定されているClassインスタンスたい:

public void MyTest(IInterface @interface, Class implementation) 
{ 
    Assert.Same(@interface, implementation); 
} 
+1

「フリーズ」オーバーロードは、あなたが思うようには行いません。 [ドキュメント](https://github.com/AutoFixture/AutoFixture/blob/master/Src/AutoFixture/FixtureFreezer.cs#L43-L72)を参照してください。望ましい結果を達成するためのかなり慣れ親しんだ方法の1つについてはEnrico Campidoglioの答えを参照してください。もう一つの選択肢は、AutoFixture auto-mockingコンテナ拡張の1つを使用することです。基本的には、このような機能が組み込まれています。 –

+0

謝罪@マークセーマン、私は失敗です。私はInject/Freezeに関する他の議論を見て、混乱しました。私はインジェクションとフリーズを意味せず、それに応じて質問を更新しました。 –

答えて

0

OKこれは永遠に理解することができましたが、この質問/シナリオは最終的に私の部分ではデザインが悪く、AutoFixtureを学習していないことが原因です。私がしようとしていた実際のシナリオは、IoCコンテナを自分のフィクスチャに登録することでした。IServiceLocatorとその実装をFixtureに登録して、現在のテストメソッドに値を注入できるようにしました。

これは、提供されたIServiceLocator(here in this questionとも呼ばれる)に要求を中継するためにa Customizationを追加することで解決しました。

また、私は私が探していたものを行いDynamiteyを利用しan extension methodを作るなかったが、それはもはや使用されていると私はおそらくいくつかの点で削除させていただきます。

答えはです。何らかの理由でこれを実行したい場合は、おそらくdoing it wrong以上です。私はこの答えを削除するために半分誘惑されていますが、私のような別の新作が同じ問題に遭遇し、この恩恵を受ける場合に備えてここに残します。

最後に、私は@ enrico-campidoglioと@ mark-seemannに感謝し、本当に有益な/質の高い回答/援助をしたいと思います。私はバーがここで高く設定されていることを知っている@スタックオーバーフローと私はおそらくこの質問を投稿する前にもう少し忍耐を持っている必要があります。

2

確かに、あなたは具象クラスのパラメータに[Frozen]属性を適用し、マッチング等のImplementedInterfacesを指定することができます基準:

​​

それはその実装の任意のの値を作成する必要があり同じClassインスタンスごとに時間を提供するためにAutoFixtureを伝えますedインタフェース。

+0

答えてくれてありがとう、@ enrico-campidoglio。私はもっ​​と明確ではないことをお詫びします、私は注射して凍らないようにしています。さらに、属性レベルではなく、ICustomization内で注入することを検討しています。私は質問をより簡潔/正確に更新しました。私の新しさを許してください! –

4

あなたはInject方法を詳しく見てみると、あなたは絶対にそれを自分

を行う必要がある場合、あなたはそれが実際に一般的な方法だとわかりますが、あなたがそれを使用するようにあなたがそれを使用するときに型引数が推測されています。両方をフリーズしたい場合は、それぞれのタイプに対してInjectを呼び出すだけで済みます。

ここには少し修正したCustomizationがあります。 Customizeが二回同じアイテムを注入

public class Customization : ICustomization 
{ 
    readonly Class item; 

    public Customization() : this(new Class()) { } 

    public Customization(Class item) 
    { 
     this.item = item; 
    } 

    public void Customize(IFixture fixture) 
    { 
     fixture.Inject(item); 
     fixture.Inject<IInterface>(item); 
    } 
} 

ていることに注意してください:そのitemフィールド(および対応するitemコンストラクタの引数が)タイプClassであるように、おそらく無効なダウンキャストを防ぐために、私はそれを変更しました。最初の行では、汎用型の引数はコンパイラによってClassに推測されますが、2行目では型引数IInterfaceが明示的に定義されています。この実装を考えると

、以下のテストは合格:

ビルトインAPI

私はそれが簡単に、単純に内蔵されたAPIを使用するために検討したい、と述べているすべての使用

[Fact] 
public void UseCustomization() 
{ 
    var fixture = new Fixture().Customize(new Customization()); 

    var c = fixture.Create<Class>(); 
    var i = fixture.Create<IInterface>(); 

    Assert.Equal(c, i); 
} 

IInterfaceのためのすべての要求が要求Fに中継されることを意味します
[Fact] 
public void UseTypeRelay() 
{ 
    var fixture = new Fixture(); 
    fixture.Customizations.Add(
     new TypeRelay(
      typeof(IInterface), 
      typeof(Class))); 
    fixture.Freeze<Class>(); 

    var c = fixture.Create<Class>(); 
    var i = fixture.Create<IInterface>(); 

    Assert.Equal(c, i); 
} 

TypeRelayマップClassからIInterface、またはClassClassが固定されている場合は、Classが凍結されているだけでなく、IInterfaceも凍結されていることを意味します。

関連する問題