我只想处理特定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)方法在线,但这似乎不公开访问。)

有帮助吗?

解决方案

克服这一障碍的最小努力将是一个静态帮助器/实用程序方法,它使用反射来破解所需错误代码中的插槽。使用最优秀的Reflector,我看到有一个私有的“errorCode”。 field,仅通过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

其他提示

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

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top