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

克服这个障碍的最少努力是使用反射来破解所需错误代码中的静态帮助器/实用程序方法。使用最优秀的反射器,我看到有一个私有的“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);
      }

尽管我通常不赞成在测试中进行反思,但这是需要/有用的罕见情况之一。
高温高压

于 2009-07-06T05:42:30.923 回答
1

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

于 2009-07-06T03:50:58.183 回答
0

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

编辑:可以想象,ErrorCode不能被覆盖(我讨厌如此僵化的语言,以至于他们可以以这种方式停止测试,但不能否认它们存在;-)。在这种情况下,依赖注入仍然可以拯救你——DI 是我最喜欢的测试模式之一。

DI 在测试中的目的是将被测代码与会抑制可测试性的严格假设分离——这正是我们在这里所拥有的,尽管是以一种不寻常的形式。例如,您的被测代码当前确实x.ErrorCode会获取异常 x 的错误代码。很好,然后它必须做,而不是,通常只做的委托getErrorCode(x)在哪里;并且它必须有一个委托的设置器,以便出于测试目的,您可以将其更改为一个委托(或您想要模拟以进行测试的任何错误代码值)。getErrorCodereturn x.ErrorCodegetErrorCodereturn 23

细节可能会有所不同,但依赖注入可以(除其他外)帮助补偿您不可避免地从系统(或您无法直接修改的其他库和c)获得的对象中的某些过度僵化,如本例所示。

于 2009-07-06T03:53:48.083 回答
0

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

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

于 2009-07-06T04:24:13.310 回答