2012-04-05 12 views
1

のいくつかの並べ替え(アヒルパンチは、より正確な用語でもよい)高度に結合されたコードのユニットテスト.net;モックを注入する反射?

class Foo{ 
    private Bar highlyCoupled = new highlyCoupled(); 

    public bool DoTheThing(){ 
    return highlyCoupled.doesTheThing(); 
    } 
} 

がfooを開いて注入するためにリフレクションを使用することが可能です...のは、私が何かのように見えるのクラスの束を持っているとしましょうmockHighlyCoupledは、結合の高い場所にありますか?このような状況で約...

class DoubleFoo : Foo{ 
    public bool DoTheOtherThing(){ 
    return DoTheThing(); 
    } 
} 

はhighlyCoupledはそれの場所に挿入されたモックを持って何を

を継承することはできますか?

反射を必要としないようにコードをリファクタリングすることは、残念ながら不可能です。

+1

2行目に構文エラーがあります。 –

+1

深刻なリファクタリングがなければ、テストは非常に脆くなる可能性があります。 – jrummell

+0

あなたは何を求めていますか?リフレクションを使用してプライベートメンバーを設定できますか?はい、できます。そうすることに問題がありますか? – cadrell0

答えて

1

モッキングフレームワークを使用してリファクタリングすることができないため、これは少し楽になります。

TypeMock:

var fakeType = Isolate.Fake.Instance<SomeType>(); 
ObjectState.SetField(fakeType, "_somePrivateField", myValue); 

MOQ:たとえば

var fakeType = new Mock<SomeType>() 
fakeType.Protected().Setup<SomeType>("_somePrivateField").Returns(myValue); 

正直に言うと、私は実際に部品番号でこれを試していないが、私はそれはあなたが必要なものをやると思います。

+0

ありがとう、これは最も有用な答えのように見えます。非常にユニークな状況のようには思えませんでした。 – MushinNoShin

+0

Moqのどのバージョンに 'Protected()'メソッドがありますか?私はMoqをダウンロードしました。そうでなければ実行時にMEFによって作成されるプライベートフィールドにモックを注入する必要があります。 – IAbstract

+0

ドキュメントに従って最新バージョンにする必要があります。 http://code.google.com/p/moq/wiki/QuickStart#Miscellaneous – richk

0

あなたがリファクタリングすることができない場合(highlyCoupledを保護する)、あなたは反射を使用して立ち往生しています。これにより、変更なしでhighlyCoupledの値を設定できるようになります。

+0

内部も機能します。 – bryanbcook

0

私は一般にRobに同意します。依存関係をより疎結合にするためにこれをリファクタリングできない場合(少なくとも、テストプロキシのような派生クラスがデフォルト値をオーバーライドできるようにする)、可視性にもかかわらず値を設定するリフレクションは、行くことができる。

少なくともあなたができることは、依存関係を保護することです。これは、現在または将来の任意の時点で可能である場合は、それを行う:あなたは確かに反射し、嘲笑タイプを使用することができます

class Foo{ 
    protected Bar highlyCoupled = new highlyCoupled(); 

    public bool DoTheThing(){ 
    return highlyCoupled.doesTheThing(); 
    } 
} 

... 

//in your test suite  
class FooTestProxy:Foo 
{ 
    public FooTestProxy(Bar testMock) 
    { 
     highlyCoupled = testMock; 
    } 
} 

//now when testing, instantiate your test proxy and pass it the mocked object 
1

が、その型が元の型から継承する必要があります(FieldInfo.SetValueは、そうでない場合は失敗します)。

void Main() 
{ 
    var bar = new Bar(); 
    var type = typeof(Bar); 
    // Get the type and fields of FieldInfoClass. 
    var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); 
    fields[0].SetValue(bar, new FooMock()); // you can use new Foo() here too. 
    bar.Print(); 
} 

class Foo { 
    public int i = 0; 
} 

class FooMock : Foo { 
} 

class Bar { 
    private Foo foo = new Foo(); 

    public void Print() { 
     Console.WriteLine(i); 
    } 
} 
関連する問題