2

次の例では、TestMe.DoSomething()関数をテストします。

このメソッド内で使用されるインターフェイスをモックし、ISomething別の値を返すようにします (特定の単体テストに応じて)。

実生活では、ISomethingインターフェースは高価なサードパーティのリソースを呼び出すことになりますISomething.

構造の例を次に示します。

class TestMe
{
    public void DoSomething()
    {
        ISomething s = SomethingFactory();
        int i = s.Run();

        //do things with i that I want to test
    }

    private ISomething SomethingFactory()
    {
        return new Something();
    }
}

interface ISomething
{
    int Run();
}

class Something : ISomething
{
    public int Run()
    {
        return 1;
    }
}

動作しないコードは次のとおりです。

        var fakeSomething = new Mock<ISomething>();
        var testMe = new TestMe();
        Mock.Get(testMe).Setup(p => p.SomethingFactory()).Returns(fakeSomething.Object);
        testMe.DoSomething();

SomethingFactory()isであるためprivate、そのメソッドからの戻り値を希望どおりに設定することはできません。

これを解決する方法について何かアドバイスはありますか?

4

3 に答える 3

3

ファクトリを完全なインターフェイス/クラスにして、TestMe から SomethingFactory メソッドを削除します。

public interface ISomethingFactory {
  ISomething MakeSomething();
}

public sealed class SomethingFactory {
  public ISomething MakeSomething() {
    return new Something();
  }
}

class TestMe
{
    private readonly ISomethingFactory _somethingFactory;

    public TestMe(ISomethingFactory somethingFactory) {
      _somethingFactory = somethingFactory;
    }

    public void DoSomething()
    {
        ISomething s = _somethingFactory.MakeSomething();
        int i = s.Run();

        //do things with i that I want to test
    }
}

これにより、ISomethingFactory をモックして ISomething のモックを返すことができます。

このソリューションはあまりにも劇的な変更であると抗議するかもしれませんが、仮想化する唯一の理由がテストのためであるメンバーで封印されていないクラスを作成するよりはましだと思います。

于 2013-05-17T18:22:26.483 に答える
1

SomethingFactory() を保護された仮想に変更すると、 Moq.Protected を使用してその名前でメソッドにアクセスできます。

public class TestMe 
{
    public void DoSomething()
    {
        ISomething s = SomethingFactory();
        int i = s.Run();

        //do things with i that I want to test
    }

    protected virtual ISomething SomethingFactory()
    {
        return new Something();
    }
}

public interface ISomething
{
    int Run();
}

public class Something : ISomething
{
    public int Run()
    {
        return 1;
    }
}

したがって、このテストを実行できます。

        var fakeSomething = new Mock<ISomething>();
        fakeSomething.Setup(p => p.Run()).Returns(2);
        var testMe = new Mock<TestMe>();
        testMe.Protected().Setup<ISomething>("SomethingFactory").Returns(fakeSomething.Object);
        testMe.Object.DoSomething();
于 2013-05-17T18:15:42.253 に答える