Question

Je souhaite gérer une exception ManagementException pour un code d'erreur spécifique uniquement et je ne parviens pas à écrire le test unitaire correspondant. D'ordinaire, j'écrirais le test pour qu'il ressemble à ceci:

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

...

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

...

Cependant, cela ne définit pas le code d'erreur comme celui que je veux en particulier, en effet, ManagementException n'a pas de constructeur qui définit cette valeur.

Comment cela peut-il être fait?

(Notez que j'utilise RhinoMocks comme cadre moqueur, mais je suppose qu'il est indépendant du cadre; tout ce que j'ai besoin de savoir, c'est comment créer une exception ManagementException qui a une valeur ErrorCode spécifique. J'ai également trouvé quelques références à une méthode System.Management.ManagementException.ThrowWithExtendedInfo (ManagementStatus errorCode) en ligne, mais elle ne semble pas être accessible au public).

Était-ce utile?

La solution

Le moindre effort pour surmonter cet obstacle serait une méthode d'assistance statique / utilitaire qui utilise la réflexion pour pirater l'emplacement du code d'erreur requis. En utilisant le réflecteur le plus performant, je vois qu’il existe un "errorCode" privé. champ, qui est défini uniquement via les acteurs internes définis dans ManagementException. Donc:)

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

Vérifié que cela fonctionne

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

Bien que les sourcils froncés me causent des problèmes de réflexion , il s'agit de l'un des rares cas où cela est nécessaire / utile.
HTH

Autres conseils

Dérivez une classe de ManagementException et cachez l'implémentation du code d'erreur avec la vôtre. Demandez à votre maquette de retourner ce cours.

Utilisez une méthode ou une classe très simple et très petite qui capture cette exception et en extrait le code d'erreur, puis la transmet à la vraie classe qui effectue le travail. Sous test, remplacez ce code par un transfert direct à la classe réelle de ce que vous transmettriez lorsque vous obtenez ce code d'erreur.

La méthode la plus évidente consiste à sous-classer l'exception, mais si cela ne fonctionne pas, le code qui l'attrape et lève immédiatement votre propre exception permettant d'exposer ce code constituerait une autre option.

Je voudrais sous-classe ManagementException et dans la sous-classe remplacer le getter ErrorCode (si les niveaux de protection normaux vous empêchent de le faire, l'introspection pourrait peut-être vous rapprocher). Tout code qui gère ManagementException mais n'a jamais entendu parler de votre sous-classe spécifique doit gérer votre sous-classe "comme si". c’est bien la ManagementException que vous essayez de simuler à des fins de test.

Modifier : il est concevable que ErrorCode ne puisse tout simplement pas être remplacé (je déteste les langues tellement rigides qu'elles peuvent arrêter les tests de cette façon, mais ne peuvent nier leur existence; -). Dans ce cas, Dependency Injection peut toujours vous sauver. DI est l’un de mes modèles préférés pour les tests.

L'objectif de DI en matière de test est de dissocier le code testé de suppositions rigides qui empêcheraient la testabilité - et c'est exactement ce que nous avons ici, bien que sous une forme inhabituelle. Par exemple, votre code testé est, par exemple, x.ErrorCode pour obtenir le code d'erreur de l'exception x. Très bien, il faut alors faire getErrorCode (x) getErrorCode est un délégué qui normalement ne fait que renvoyer x.ErrorCode ; et il doit avoir un paramètre pour le délégué getErrorCode , de sorte que vous puissiez le modifier à des fins de test en un délégué qui renvoie 23 (ou toute valeur de code d'erreur que vous avez définie). vouloir simuler pour les tests).

Les détails peuvent varier, mais l'injection de dépendance peut (entre autres choses) aider à compenser certains types de rigidité excessive d'objets que vous obtenez inévitablement du système (ou d'autres bibliothèques que vous ne pouvez pas modifier directement), comme dans ce cas. exemple.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top