如何设置ManagementException的ErrorCode?

时间:2009-06-18 04:25:37

标签: unit-testing exception mocking error-code

我只想处理特定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 个答案:

答案 0 :(得分:3)

克服这个障碍的最小努力将是一个静态帮助器/实用程序方法,它使用反射来破解所需错误代码中的插槽。使用最优秀的Reflector,我看到有一个私有的“errorCode”字段,它只能通过ManagementException中定义的内部ctors设置。所以:)

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);
      }

虽然我通常对测试中的反思感到不满,但这是极少数需要/有用的情况之一。
HTH

答案 1 :(得分:1)

从ManagementException派生一个类并使用您自己的隐藏错误代码实现。让你的模拟返回这个课程。

答案 2 :(得分:0)

我会继承ManagementException并在子类中覆盖ErrorCode getter(如果正常的保护级别阻止你这样做,也许内省可以让你更接近)。处理ManagementException但从未听说过您的特定子类的任何代码都应该处理您的子类“就好像”它是您试图为测试目的而模拟的ManagementException

编辑:可以想象ErrorCode无法被覆盖(我讨厌那种严格的语言,他们可以用这种方式停止测试,但不能否认它们存在;-)。在这种情况下,依赖注入仍然可以为您节省 - DI是我最喜欢的测试模式之一。

DI的测试目的是将测试中的代码与可能抑制可测试性的严格假设分离 - 而这正是我们在这里所拥有的,尽管是一种不同寻常的形式。您正在测试的代码当前会执行x.ErrorCode以获取异常x的错误代码。很好,相反,它必须getErrorCode(x),其中getErrorCode是一个通常只有return x.ErrorCode的委托;并且它必须具有getErrorCode委托的setter,以便出于测试目的,您可以将其更改为执行return 23的委托(或您要模拟用于测试的任何错误代码值)。

细节可以有所不同,但依赖注入可以(除其他外)有助于补偿你不可避免地从系统(或从你无法直接修改的其他库和c)中获得的对象中的某种过度刚性,如此示例

答案 3 :(得分:0)

有一个非常简单的小方法或类来捕获异常并从中获取错误代码,然后将其传递给执行工作的真正类。在测试中,将代码替换为直接传递给实际类,当您获得该错误代码时将通过该代码。

最明显的方法是对异常进行子类化,但是如果这不起作用,那么捕获它的代码会立即抛出你自己的异常,它允许你公开该代码,这将是另一种选择。