8

以下usingは、私が実際にヒットしたくない外部リソースにヒットします。テストしたいのですsomeResultが、それを使用するコードをテストしますが、単体テストを実行するたびに、このコードは実際のWebサービスにアクセスしようとします。moqを使用してWebサービスへの実際の呼び出しを偽造するが、使用中の残りのコードをモックしないようにするにはどうすればよいですか?

public IMyInterface.SomeMethod()
{    
     // hits a web service
     using ( mySoapClient client = new mySoapClient() )
     {
          var someResult = client.DoSomething();
       ...
       ...
     }
}


[TestMethod()]
public void SomeMethodTest()
{
    IMyInterface target = new MyInterface();
    target.SomeMethod();

    // Assert....
}
4

3 に答える 3

14

Webサービスの実装をコンシューマーから切り離す必要があります

public class ClassIWantToTest
{
      public ClassIWantToTest(IServiceIWantToCall service) {}

      public void SomeMethod()
      {
           var results = service.DoSomething();
           //Rest of the logic here
      }
}

これで、Moqを使用してIServiceIWantToCall、のロジックをテストするためにモックを作成できます。SomeMethod

于 2012-08-30T19:46:37.927 に答える
2

ピクルスの答えに追加するinterfaceために、現在のサービス呼び出し用にを作成しましたIService。次に、インターフェイスを継承するクラスを作成し、ServiceMockという名前のグローバル変数を追加しました_service。コンストラクターで、モックサービスをインスタンス化し、インターフェイスのすべてのメソッドを次のように設定します。

public class ServiceMock : IService
{
    Mock<IService> _serviceMock;

    public ServiceMock()
    {
        _serviceMock = new Mock<IService>();

        _serviceMock.Setup(x => x.GetString()).Returns("Default String");

        SomeClass someClass = new SomeClass();
        someClass.Property1= "Default";
        someClass.Property2= Guid.NewGuid().ToString();

        _serviceMock.Setup(x => x.GetSomeClass()).Returns(someClass);
    }

    public string GetString()
    {
        return _serviceMock.Object.GetString();
    }

    public License GetSomeClass()
    {
        return _serviceMock.Object.GetSomeClass();
    }
}

次に、実際のWebサービスではなく、このクラスをコードに挿入します。設定した値を返します。これで、Webサービスに依存せずにテストできます。

于 2014-03-31T19:23:46.717 に答える
1

まず、Webサービスを挿入できる必要があります。SomeMethod()内に新しいメソッドを作成すると、メソッドが本番コードに「緊密に結合」されます。mySoapClient以外のものを作成するように動的に指示することはできません。

それらを作成して破棄したいので、テストしたいコードがFunc<IMySoapClient>メソッドパラメーターまたはコンストラクターパラメーターとして受け入れることをお勧めします。次のようになります。

public IMyInterface.SomeMethod(Func<IMySoapClient> clientFactory)
{    
     // hits a web service
     using ( mySoapClient client = clientFactory() )
     {
          var someResult = client.DoSomething();
       ...
       ...
     }
}

... また:

public class MyClass:IMyInterface
{
   private Func<IMySoapClient> MySoapClientFactoryMethod;

   public MyClass(Func<IMySoapClient> clientFactoryMethod)
   {
      MySoapClientFactoryMethod = clientFactoryMethod;
   }

   ...

   public IMyInterface.SomeMethod()
   {    
        // hits a web service
        using ( mySoapClient client = MySoapClientFactoryMethod() )
        {
             var someResult = client.DoSomething();
          ...
          ...
        }
   }
}

ここで、テストしようとしているオブジェクトを作成するときに、Soapサービスの適切なMoqモックを生成する関数を定義します。これは、副作用なしに実際のクライアントに期待される動作を持ちます(コードDispose()d(クライアントの)を実行し、その関数をテストしているクラスまたはメソッドに渡します。本番環境では、関数をとして定義する()=>new mySoapClient()か、IoCフレームワークを設定してmySoapClientをIMySoapClientとして登録してから、MyClassを登録することができます。ほとんどのIoCフレームワークは、デリゲートをパラメーターとして認識し、登録された依存関係を挿入するメソッドを生成するのに十分スマートです。

于 2012-08-30T19:52:22.753 に答える