1

特定の ErrorCode に対してのみ ManagementException 例外を処理したいのですが、単体テストの作成に問題があります。通常、次のようになるようにテストを記述します。

Searcher search = MockRepository.GenerateMock<Searcher>(); 
// wrapper for ManagementObjectSearcher

...

search.Expect(s => s.Get()).Throw(new ManagementException());

...

ただし、これは ErrorCode を特に必要なものに設定しません。実際、ManagementException にはこの値を設定するコンストラクターがありません。

これはどのように行うことができますか?

(私はモック フレームワークとして RhinoMocks を使用していますが、これはフレームワークに依存しないと想定しています。ここで知っておく必要があるのは、特定の ErrorCode 値を持つ ManagementException を作成する方法だけです。また、System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)オンラインでメソッドへの参照をいくつか見つけました。しかし、これは公にアクセスできるようには見えません)。

4

4 に答える 4

3

このハードルを乗り越えるための最小の努力は、必要なエラーコードでスロットをハックするためにリフレクションを使用する静的ヘルパー/ユーティリティメソッドです。最も優れたReflectorを使用すると、ManagementExceptionで定義された内部ctorを介してのみ設定されるプライベートな「errorCode」フィールドがあることがわかります。それで :)

public static class EncapsulationBreaker
   {
      public static ManagementException GetManagementExceptionWithSpecificErrorCode(ManagementStatus statusToBeStuffed)
      {
         var exception = new ManagementException();
         var fieldInfo = exception.GetType().GetField("errorCode", 
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.DeclaredOnly);
         fieldInfo.SetValue(exception, statusToBeStuffed);
         return exception;
      }
   }

動作することを確認しました

[Test]
      public void TestGetExceptionWithSpecifiedErrorCode()
      {
         var e = EncapsulationBreaker.GetManagementExceptionWithSpecificErrorCode(ManagementStatus.BufferTooSmall);
         Assert.AreEqual(ManagementStatus.BufferTooSmall, e.ErrorCode);
      }

私は一般的にテストでの反省に眉をひそめますが、これはそれが必要/有用であるまれなケースの1つです。
HTH

于 2009-07-06T05:42:30.923 に答える
1

ManagementException からクラスを派生させ、エラー コードの実装を独自のもので非表示にします。モックにこのクラスを返させます。

于 2009-07-06T03:50:58.183 に答える
0

その例外をキャッチしてエラーコードを取得し、それを作業を行う実際のクラスに渡す、非常に単純で小さなメソッドまたはクラスを用意します。テスト中は、そのコードを実際のクラスに直接渡して、そのエラー コードを取得したときに渡すものに置き換えます。

最も明白な方法は例外をサブクラス化することですが、それがうまくいかない場合は、それをキャッチし、すぐに独自の例外をスローして、そのコードを公開できるようにするコードが別のオプションになります。

于 2009-07-06T04:24:13.310 に答える
0

私はサブクラスManagementException化し、サブクラスで getter をオーバーライドしますErrorCode(通常の保護レベルでそれができない場合は、イントロスペクションによってさらに近づくことができます)。ManagementException特定のサブクラスを処理するが聞いたことがないコードはManagementException、結局のところ、テスト目的でシミュレートしようとしているものであるかのように、サブクラスを処理する必要があります。

編集ErrorCodeオーバーライドできないことも考えられます(このようにテストを停止できるほど厳格な言語は嫌いですが、それらの存在を否定することはできません;-)。この場合でも、依存関係の挿入によって問題を解決できます。DI は、私のお気に入りのテスト パターンの 1 つです。

テストにおける DI の目的は、テスト容易性を阻害する厳格な仮定からテスト対象のコードを分離することです。これは、通常とは異なる形式ではありますが、まさにここにあるものです。テスト中のコードは現在、たとえば、x.ErrorCode例外 x のエラー コードを取得しています。代わりに、getErrorCode(x)where getErrorCodeis a delegate が通常は; を実行する必要がありreturn x.ErrorCodeます。また、デリゲート用のセッターが必要ですgetErrorCode。これにより、テスト目的で、それをデリゲートreturn 23(またはテスト用にシミュレートするエラー コード値) に変更できます。

詳細はさまざまですが、この例のように、システムから (または直接変更できない他のライブラリ &c から) 必然的に取得するオブジェクトの過度の硬直性を補うために、依存性注入が (とりわけ) 役立ちます。

于 2009-07-06T03:53:48.083 に答える