9


1

WCF障害の単体テスト

WCFサービスから予想される障害を単体テストする最良の方法は何ですか?

特定の再現可能なエラーに対してFaultExceptionsを(正しく)スローしているWCFサービスを単体テストしようとしています。 単体テストは、WCFクライアントのインスタンスを取得し、該当するサービスメソッドを呼び出して、FaultExceptionをスローします。

これらはすべて期待どおりに機能しますが、サービス実装でエラーがキャッチされない場合、フォールトによりIDEが破損するため、ユニットテストを行うのが困難です。 私は例外ではなく障害を使用しているため、IDEが例外をシリアル化してクライアントに送信し、そこで例外が発生することを期待していました。

特定のユーザーが処理しない例外のブレークを無効にする設定オプションがあることはわかりますが、チーム環境では簡単に実行できないため、誰かが同じ結果を達成するためのより良い方法を指摘できることを望んでいました。

以下は、実装が現在どのように見えるかのサンプルコードです…​

単体テストプロジェクトには、WCFサービスへのサービス参照があり、インターフェイスを次のように定義しています。

[OperationContract(Name = "DoSomething")]
[FaultContract(typeof(EpicFail))]
ResponseObject DoSomething(RequestObject requestObject);

障害は次のように定義されます。

[DataContract]
public class EpicFail
{

    public EpicFail(string action)
    {
        this.Reason = "Epic Fail";
        this.Action = action;
    }

    [DataMember]
    public string Reason
    {
        get;
        set;
    }

    [DataMember]
    public string Action
    {
        get;
        set;
    }

}

サービスを呼び出すコードは、次のようにあいまいに見えます。

[TestMethod()]
[ExpectedException(typeof(FaultException))]
public void FaultTest_Fails_Epicly()
{
    bool testPassed = false;

    try
    {
        ResponseObject resp = GetServiceClient().DoSomething(req);
    }
    catch (FaultException)
    {
        testPassed = true;
    }

    Assert.IsTrue(testPassed);
}
  • ExpectedExceptionを使用していることを示すためにコードを編集しました 属性であり、サービスで例外がスローされたときにIDE /デバッガーが壊れないようにするのにあまり効果がないようです。

2 Answer


1


これがスローされる例外であることを確認するために、常に(NUnitで) `ExpectedExceptionAttribute`を使用できます。 MSTestにも同様の概念があります。

[ExpectedException(typeof(MyException))]
void my_test()
{
     // test
}

モック検証を行う必要がある場合は、try / catchブロックを使用してcatchで検証し、例外をスローします。

更新

`ExpectedException`属性を使用している場合、例外をキャッチすることは想定されていません。代わりに、テストを実行するNUnitにそれをキャッチさせる必要があります。

例外の特別な情報を確認する必要がある場合は、例外をキャッチし、情報を確認してから再スローします。

[ExpectedException(typeof(MyException))]
void my_test()
{
     try
     {
         // call the service
     }
     catch(MyException ex)
     {
          Assert.IsTrue(ex.Message.Contains("error code 200"));
          throw ex;
     }

}


1


mattv、

このテストがサービスに*リモート*でアクセスする必要があるのはなぜですか? 私があなたのコードを見るところから:

ResponseObject resp = GetServiceClient().DoSomething(req);

サービスインスタンス自体ではなく、何らかの形でサービスクライアントを取得しています。 ユニットテストのために、サービスコンクリートクラスを直接テストすることをお勧めします。

ただし、このシナリオが*必要*の場合、例外をキャッチせずにテストを実行しようとしましたか? 同じ結果が得られますか?

ところで、キャッチして再スローする必要がある場合は、次のパターンを使用します。

try {
   //Do something
}
catch(SomeException e) {
   //Do something with e
   throw
}