ManagementExceptionのErrorCodeを設定する方法は?
-
06-07-2019 - |
質問
特定のErrorCodeのみのManagementException例外を処理したいのですが、単体テストの記述に問題があります。通常、次のようなテストを作成します。
Searcher search = MockRepository.GenerateMock<Searcher>();
// wrapper for ManagementObjectSearcher
...
search.Expect(s => s.Get()).Throw(new ManagementException());
...
ただし、これは特に希望するErrorCodeにErrorCodeを設定しません。実際、ManagementExceptionにはこの値を設定するコンストラクターがありません。
これはどのように行うことができますか?
(RhinoMocksをモックフレームワークとして使用していますが、これはフレームワークに依存しないと仮定しています。ここで知る必要があるのは、特定のErrorCode値を持つManagementExceptionを作成する方法だけです。 System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
メソッドはオンラインですが、これは公開されていないようです)
解決
このハードルを乗り越えるための最小の努力は、必要なエラーコードのスロットをハックするためにリフレクションを使用する静的なヘルパー/ユーティリティメソッドです。最も優れたReflectorを使用すると、プライベートな「errorCode」があります。フィールド。ManagementExceptionで定義された内部アクタを介してのみ設定されます。だから:)
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
他のヒント
ManagementExceptionからクラスを派生し、独自のエラーコード実装を非表示にします。モックにこのクラスを返させてください。
非常にシンプルで小さなメソッドまたはクラスを用意し、その例外をキャッチしてエラーコードを取得し、作業を実行する実際のクラスに渡します。テスト中に、そのコードを、そのエラーコードを取得したときに渡すものを実際のクラスに直接渡すことで置き換えます。
最も明白な方法は例外をサブクラス化することですが、それが機能しない場合、それをキャッチし、そのコードを公開できる独自の例外をすぐにスローするコードは別のオプションになります。
ManagementException
のサブクラスを作成し、サブクラスで ErrorCode
ゲッターをオーバーライドします(通常の保護レベルでそれができない場合は、イントロスペクションを使用するとより近くなる可能性があります)。 ManagementException
を処理するが、特定のサブクラスについて聞いたことがないコードは、サブクラス&quot; if&quot;を処理する必要があります。結局のところ、テスト目的でシミュレートしようとしているのは ManagementException
でした。
編集: ErrorCode
をオーバーライドすることはできないと考えられます(この方法でテストを停止できるが、存在を否定できないほど厳格な言語は嫌いです。 -)。この場合、依存性注入はあなたを救うことができます-DIはテストのための私のお気に入りのパターンの1つです。
DIのテストの目的は、テスト対象のコードを、テスト容易性を妨げる厳格な仮定から切り離すことです。これは、異常な形式ではありますが、まさにここにあります。現在、テスト対象のコードは、たとえば x.ErrorCode
を実行して、例外xのエラーコードを取得します。非常によく、代わりに getErrorCode(x)
を実行する必要があります。ここで、 getErrorCode
は通常 return x.ErrorCode
を行うデリゲートです。また、 getErrorCode
デリゲートのセッターが必要です。テスト目的で、 return 23
(またはエラーコード値)を行うデリゲートに変更できます。テスト用にシミュレートしたい)。
詳細は異なる場合がありますが、依存性注入は(特に)システムから(または直接変更できない他のライブラリ&amp; cから)必然的に取得するオブジェクトのある種の過度の剛性を補正するのに役立ちます。例。