3

私はいくつかの外部依存関係のモックに取り組んでおり、別のサードパーティ クラスのインスタンスをコンストラクターに取り込むサードパーティ クラスで問題が発生しています。SOコミュニティが私に何らかの方向性を与えてくれることを願っています。

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

リポジトリコード...

これは、テスト コンソール アプリケーションで使用している Main メソッドです。

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 できるようにするために使用したクラスです。

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

2 に答える 2

10

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

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

次に、すべての呼び出しをサード パーティ クラスにルーティングする実装を作成します。

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

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

SomeRelatedLibraryClass に依存するアプリ内のクラスは、代わりに ISomeRelatedLibraryClassGateway に依存できるようになり、このインターフェイスは簡単にモックできます。クラス SomeRelatedLibraryClassGateway は、実際には単体テストを必要としません。コールをパススルーするだけです。機能テストでテストする必要ありますが、モックなしで機能テストを実行できます。

お役に立てれば。

于 2009-08-03T02:56:28.003 に答える
2

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

于 2009-08-03T02:36:32.677 に答える