2009-08-03 14 views
3

私はいくつかの外部依存関係を嘲笑に取り組んでいて、別のサードパーティクラスのインスタンスをそのコンストラクタに取り込む1つのサードパーティクラスに問題があります。うまくいけば、SOのコミュニティは私にある方向性を与えることができます。これはMoqでモックできますか?

SomeLibraryClassのモックインスタンスをコンストラクタに取り込むSomeRelatedLibraryClassのモックインスタンスを作成したいとします。どうすればこのようにSomeRelatedLibraryClassを模擬することができますか?

レポコード ...ここ

は、私は私のテストコンソールアプリケーションで使用している主な方法です。 (ここでは

public class MyClass 
{ 
    private SomeLibraryClass _SLC; 

    public MyClass(string constructMsg) 
    { 
     _SLC = new SomeLibraryClass(constructMsg); 
    } 

    public virtual void WriteMessage(string message) 
    { 
     _SLC.WriteMessage(message); 
    } 
} 

は、私が働いているサードパーティのクラスの2つの例は次のとおりです。ここ

public static void Main() 
{ 
    try 
    { 
     SomeLibraryClass slc = new SomeLibraryClass("direct to 3rd party"); 
     slc.WriteMessage("3rd party message"); 
     Console.WriteLine(); 

     MyClass mc = new MyClass("through myclass"); 
     mc.WriteMessage("myclass message"); 
     Console.WriteLine(); 

     Mock<MyClass> mockMc = new Mock<MyClass>("mock myclass"); 
     mockMc.Setup(i => i.WriteMessage(It.IsAny<string>())) 
      .Callback((string message) => Console.WriteLine(string.Concat("Mock SomeLibraryClass WriteMessage: ", message))); 

     mockMc.Object.WriteMessage("mock message"); 
     Console.WriteLine(); 
    } 
    catch (Exception e) 
    { 
     string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString()); 
     Console.WriteLine(error); 
    } 
    finally 
    { 
     Console.Write("Press any key to continue..."); 
     Console.ReadKey(); 
    } 
} 

は、私は1つのサードパーティのクラスをラップし、それがMoq'dことを可能にするために使用しているクラスです お客様がこれらを編集することはできません):

public class SomeLibraryClass 
{ 
    public SomeLibraryClass(string constructMsg) 
    { 
     Console.WriteLine(string.Concat("SomeLibraryClass Constructor: ", constructMsg)); 
    } 

    public void WriteMessage(string message) 
    { 
     Console.WriteLine(string.Concat("SomeLibraryClass WriteMessage: ", message)); 
    } 
} 

public class SomeRelatedLibraryClass 
{ 
    public SomeRelatedLibraryClass(SomeLibraryClass slc) 
    { 
     //do nothing 
    } 

    public void WriteMessage(string message) 
    { 
     Console.WriteLine(string.Concat("SomeRelatedLibraryClass WriteMessage: ", message)); 
    } 
} 

答えて

2

私の知る限り、あなたはモックしようとしているクラスが仮想またはインタフェースではない場合 - あなたは部品番号とそれを嘲笑することはできません。あなたのサードパーティのライブラリがクラスを実装していない場合、あなたは運が悪いと思います。

10

Gatewayパターンを使用することをお勧めします。 SomeRelatedLibraryClassに直接依存するのではなく、インターフェイスISomeRelatedLibraryClassGatewayを作成します。 ISomeRelatedLibraryClassGatewayで同じシグネチャのメソッドで呼び出す必要がある、すべてのSomeRelatedLibraryClassメソッドを公開します。

public interface ISomeRelatedLibraryClassGateway { 
    void WriteMessage(string message); 
} 

その後のルートすべてのサードパーティ製のクラスへの呼び出しの実装を作成:SomeRelatedLibraryClassに依存するであろうあなたのアプリ内のクラスは今の代わりにISomeRelatedLibraryClassGatewayに依存することができます今すぐ

public class SomeRelatedLibraryClassGateway : ISomeRelatedLibraryClassGateway { 
    private readonly SomeRelatedLibraryClass srlc; 
    public SomeRelatedLibraryClassGateway(SomeRelatedLibraryClass srlc) { 
    this.srlc = srlc; 
    } 

    void ISomeRelatedLibraryClassGateway.WriteMessage(string message) { 
    srlc.WriteMessage(message); 
    } 
} 

を、このインターフェイスは、模擬するのは簡単です。 SomeRelatedLibraryClassGatewayクラスは単体テストを必要としません。それは通話を通過することだけです。 は機能テストでテストする必要がありますが、モックなしで機能テストを行うことはできます。

これが役に立ちます。

+0

実際問題は、SomeLibraryClass型のパラメータとして持つSomeRelatedLibraryClassをモックする必要があることです。私は、Gatewayパターンがどのようにしてそのクラスをより簡単に模倣できるかについてはっきりしていません。私は一般に、外部依存関係を統合するときにゲートウェイパターンを使用しますが、この例では、問題に関連するとは思わないので、インタフェース定義と実装を省略しました。 –

+1

SomeRelatedLibraryClassを嘲笑することを避けることがポイントです。 Gatewayパターンを使用すると、SomeRelatedLibraryClassを欺くのを避けることができます。なぜなら、(ほとんどの)コードが直接依存しないからです。これは、コードをリファクタリングしてテストするのが簡単な例です。 –

関連する問題