2009-06-18 17 views
1

Ich möchte eine ManagementException-Ausnahme nur für einen bestimmten ErrorCode behandeln und habe Probleme beim Schreiben des Komponententests dafür. Normalerweise würde ich den Test schreiben, so dass es so etwas wie die folgende ist:Wie setze ich den ErrorCode einer ManagementException?

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

... 

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

... 

Doch dies stellt nicht den Error-Code auf die eine, die ich vor allem will, in der Tat nicht ManagementException keinen Konstruktor hat die legt diesen Wert fest.

Wie kann das gemacht werden?

(Beachten Sie, dass ich RhinoMocks als mein Spottframework verwende, aber ich gehe davon aus, dass dies Framework-unabhängig ist; alles was ich hier wissen muss ist, wie man eine ManagementException erstellt, die einen spezifischen ErrorCode-Wert hat zu einer System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode) Methode online, aber das scheint nicht öffentlich zugänglich zu sein).

Antwort

3

Der geringste Aufwand, um diese Hürde zu überwinden, wäre eine statische Hilfs-/Hilfsmethode, die Reflektion verwendet, um den erforderlichen Fehlercode zu hacken.Unter Verwendung des besten Reflectors sehe ich, dass es ein privates "errorCode" -Feld gibt, das nur über interne Ctors gesetzt wird, die in ManagementException definiert sind. So :)

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

überprüft, dass es

[Test] 
     public void TestGetExceptionWithSpecifiedErrorCode() 
     { 
     var e = EncapsulationBreaker.GetManagementExceptionWithSpecificErrorCode(ManagementStatus.BufferTooSmall); 
     Assert.AreEqual(ManagementStatus.BufferTooSmall, e.ErrorCode); 
     } 

Obwohl funktioniert im Allgemeinen ich bei der Reflexion Stirnrunzeln in Tests ist dies einer der seltenen Fälle, wo es gebraucht wird/nützlich.
HTH

+0

Genau das, was ich brauche. Vielen Dank! – jpoh

1

Leiten Sie eine Klasse von ManagementException ab und verstecken Sie die Fehlercode-Implementierung mit Ihren eigenen. Lassen Sie Ihre Klasse diese Klasse zurückgeben.

0

Ich würde ManagementException Unterklasse und in der Unterklasse die ErrorCode Getter überschreiben (wenn die normalen Schutzstufen Sie davon abhalten, vielleicht kann Introspektion Sie näher bringen). Jeder Code, der ManagementException handhabt, aber noch nie von Ihrer spezifischen Unterklasse gehört hat, sollte mit Ihrer Unterklasse umgehen, als ob es die ManagementException wäre, die Sie zu Testzwecken zu simulieren versuchen.

bearbeiten: es ist denkbar, dass ErrorCode kann einfach nicht außer Kraft gesetzt werden (I Sprachen hassen, die so starr sind, dass sie Tests auf diese Weise zu stoppen, kann aber nicht leugnen, sie existieren ;-). In diesem Fall kann Dependency Injection Sie immer noch speichern - DI ist eines meiner Lieblingsmuster zum Testen.

Der Zweck von DI besteht darin, den getesteten Code von starren Annahmen zu entkoppeln, die die Testbarkeit behindern würden - und genau das haben wir hier, wenn auch in einer ungewöhnlichen Form. Ihr Code unter Test tut z. B. x.ErrorCode, um den Fehlercode der Ausnahme x zu erhalten. Sehr gut, muss es dann stattdessen tun, getErrorCode(x) wo getErrorCode ist ein Delegat, die normalerweise nur return x.ErrorCode; und es muss einen Setter für den Delegaten getErrorCode haben, damit Sie es zu Testzwecken in einen Delegaten ändern können, der return 23 (oder welchen Fehlercode-Wert, den Sie zum Testen simulieren möchten) tut.

Einzelheiten können variieren, aber Dependency Injection kann (unter anderem) helfen Sie zwangsläufig aus dem System (oder aus anderen Bibliotheken & c, die Sie nicht direkt ändern können) bekommen für einige Arten von übermäßiger Steifigkeit in Objekten zu kompensieren, wie in diesem Beispiel.

+0

Das ist, was RhinoMocks tun würde, wenn ich eine ManagementException vortäuschen würde. Allerdings ist ErrorCode keine überschreibbare Eigenschaft. Können Sie näher erläutern, was Sie mit Introspektion meinen? – jpoh

+0

In nativen .NET ist das http://msdn.microsoft.com/en-us/library/system.reflection.aspx - aber wenn es Eigenschaften gibt, die auf diese Weise nicht überschreibbar sind, ist die Dependency-Injection die letzte, beste Hoffnung - lassen Sie mich meine Antwort entsprechend bearbeiten, um zu erklären. –

0

Haben Sie eine sehr einfache und kleine Methode oder Klasse, die diese Ausnahme abfängt und den Fehlercode daraus abruft und dann an die reale Klasse weiterleitet, die die Arbeit erledigt. Testen Sie diesen Code, indem Sie ihn direkt an die reale Klasse übergeben, was Sie weitergeben würden, wenn Sie diesen Fehlercode erhalten.

Der offensichtlichste Weg ist die Unterklasse der Ausnahme, aber wenn das nicht funktioniert, dann Code, der es abfängt, und sofort eine eigene Ausnahme auslöst, die Ihnen erlaubt, diesen Code zu enthüllen, wäre eine andere Option.

Verwandte Themen