2009-06-18 45 views
1

我想僅處理特定ErrorCode的ManagementException異常,並且無法爲其編寫單元測試。通常情況下,我會寫的測試,使其類似如下:如何設置ManagementException的ErrorCode?

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

... 

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

... 

然而,這並沒有設置錯誤代碼到,我想特別的人,確實ManagementException沒有一個構造函數,設置此值。

這怎麼辦? (注意,我使用RhinoMocks作爲我的模擬框架,但我假設這是獨立於框架的;我在這裏需要知道的是如何創建一個具有特定ErrorCode值的ManagementException,並且我已經找到了一些引用到在線System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)方法,但這似乎不公開)。

回答

3

克服這個障礙的最小努力將是一個靜態的幫助程序/實用程序方法,它在所需的錯誤代碼中使用反射到hack-slot。使用最優秀的反射器,我看到有一個私人的「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

從ManagementException派生類並使用您自己的隱藏錯誤代碼實現。讓你的模擬返回這個類。

0

我會繼承子類ManagementException,並在子類中重寫ErrorCode獲得者(如果正常的保護級別阻止你這麼做,也許內省會讓你更接近)。畢竟,處理ManagementException但從未聽說過您的特定子類的任何代碼都應該處理您的子類,好像它是您爲了測試目的而試圖模擬的ManagementException

編輯:這是可以想象的是ErrorCode只是不能被重寫(我恨是如此嚴格,他們可以阻止這樣的測試語言,但不能否認他們的存在;-)。在這種情況下,依賴注入仍然可以爲您節省 - DI是我最喜歡的測試模式之一。

DI在測試中的目的是將測試中的代碼與可能會抑制可測試性的嚴格假設分離 - 而這正是我們在這裏所得到的,儘管它是一種不尋常的形式。您目前正在測試的代碼會執行x.ErrorCode來獲取異常x的錯誤代碼。很好,它必須這樣做,相反,getErrorCode(x)其中getErrorCode是一個代表,通常只是return x.ErrorCode;並且它必須爲getErrorCode代理設置一個setter,所以出於測試目的,您可以將其更改爲代理,該代理不會爲return 23(或您想要模擬測試的任何錯誤代碼值)。

詳細信息可能會有所不同,但依賴注入可以(除其他外)幫助補償您不可避免地從系統(或不能直接修改的其他庫中的對象)中獲得的某些對象的過度剛性,例。

+0

這就是RhinoMocks如果模擬ManagementException會做什麼。但是,ErrorCode不是可覆蓋的屬性。你能否通過自省來闡述你的意思? – jpoh 2009-07-06 03:59:25

+0

在本地.NET中,即http://msdn.microsoft.com/en-us/library/system.reflection.aspx - 但如果有以這種方式不可覆蓋的屬性,則依賴注入是您的最後一個,最好的希望 - 讓我編輯我的答案相應地解釋。 – 2009-07-06 04:20:43

0

有一個非常簡單和小的方法或類,捕獲該異常並從中獲取錯誤代碼,然後將其傳遞給執行該工作的真實類。在測試中,用直接傳遞給真實類的代碼替換那些代碼,當你得到錯誤代碼時你會傳遞什麼。

最明顯的方法是對異常進行子類化,但如果這種方法不起作用,那麼捕獲它的代碼會立即拋出您自己的異常,並允許您公開該代碼,這將是另一種選擇。