web-dev-qa-db-fra.com

Comment puis-je tester une exception attendue avec un message d'exception spécifique à partir d'un fichier de ressources dans Visual Studio Test?

Le test Visual Studio peut vérifier les exceptions attendues à l'aide de l'attribut attenduException. Vous pouvez transmettre une exception comme celle-ci:

[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Vous pouvez également vérifier le message contenu dans l'exception attendue comme suit:

[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Mais lorsque vous testez des applications I18N, j'utiliserais un fichier de ressources pour obtenir ce message d'erreur (tout peut même décider de tester les différentes localisations du message d'erreur si je le souhaite, mais Visual Studio ne me laissera pas faire cela:

[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Le compilateur donnera l'erreur suivante:

Un argument d'attribut doit être une expression constante, type d'expression ou d'une expression de création de matrice d'un attribut

Quelqu'un sait-il comment tester une exception qui a un message d'un fichier de ressources?


Une option que j'ai envisagée consiste à utiliser des classes d'exception personnalisées, mais basée sur des conseils souvent entendus tels que:

"Créez et lancez des exceptions personnalisées si vous avez une condition d'erreur qui peut être traitée par programme de manière programmée de manière différente de toute autre exception existante. Sinon, lancez l'une des exceptions existantes." source

Je ne m'attends pas à gérer les exceptions différemment dans un flux normal (c'est une exception critique, alors je vais en mode panique de toute façon) et je ne pense pas que la création d'une exception pour chaque cas de test est la bonne chose à faire. Des opinions?

39
Alex Duggleby

juste Un avis, mais je dirais le texte d'erreur:

  • fait partie de l'essai, auquel cas l'obtention de la ressource serait "faux" (sinon, vous pouvez vous retrouver avec une ressource constante), alors mettez simplement à jour le test lorsque vous modifiez la ressource (ou le test échoue).
  • ne fait pas partie du test, et vous ne devez vous soucier que de l'exception.

Notez que la première option devrait vous permettre de tester plusieurs langues, étant donné la capacité de fonctionner avec un lieu local.

En ce qui concerne plusieurs exceptions à quelques exceptions près, je suis de la terre C++, où créant des charges et des charges d'exceptions (au point d'une seule par "jette"!) Dans les grandes hériamaches est acceptable (sinon commun), mais le système de métadonnées de .NET n'est probablement pas 't comme ça, d'où ce conseil.

7
Simon Buchan

L'argument de message attenduException ne correspond pas au message de l'exception. Il s'agit plutôt du message imprimé dans les résultats de test si l'exception attendue ne se produisait pas en fait.

14
user53794

Je pense que vous pouvez simplement faire une prise d'essai explicite dans votre code de test au lieu de vous appeler sur l'attribut attenduException pour le faire pour vous. Ensuite, vous pouvez proposer une méthode d'assistance qui lira le fichier de ressources et comparera le message d'erreur à celui qui est livré avec l'exception capturée. (Bien sûr, s'il n'y avait pas d'exception, le cas de test devrait être considéré comme un échec)

4
cruizer

Je me demande si Nunit descend le sentier loin de la simplicité ... mais vous y allez.

Nouvelles améliorations (2.4.3 et UP?) À L'Attribut attenduException vous permet de contrôler plus de contrôle sur les chèques à effectuer à l'exception attendue via une méthode de gestionnaire . Plus de détails sur la page page officielle Nunit Doc .. Vers la fin de la page.

[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}

public void HandlerMethod( System.Exception ex )
{
...
}

NOTE: Quelque chose ne se sent pas ici. Pourquoi vos messages d'exception sont-ils internationalisés .. Utilisez-vous des exceptions pour des choses qui doivent être traitées ou notifiées à l'utilisateur. Sauf si vous avez un groupe de développeurs culturellement diversifiés fixant des bugs. Vous ne devriez pas avoir besoin de cela. Exceptions en anglais ou une langue commune acceptée suffirait. Mais au cas où vous devriez avoir cela .. c'est possible :)

1
Gishu

Je suis tombé sur cette question tout en essayant de résoudre un problème similaire. (Je détaillerai la solution que j'ai installée ci-dessous.)

Je suis d'accord avec les commentaires de Gishu sur l'internationalisation des messages d'exception étant une odeur de code.

J'avais fait cela initialement dans mon propre projet afin que je puisse avoir la cohérence entre les messages d'erreur jetterai par mon application et dans mes tests d'unité. c'est-à-dire seulement de définir mes messages d'exception à un endroit et à l'époque, le fichier de ressources semblait être un endroit sensible pour le faire depuis que je l'utilisais déjà pour diverses étiquettes et chaînes (et comme il était logique d'ajouter une référence dans mon code de test pour vérifier que ces mêmes étiquettes montraient dans les endroits appropriés).

À un moment donné, j'avais envisagé (et testé) en utilisant des blocs Essayer/Catch pour éviter l'exigence d'une constante par l'attribut attenduException, mais cela semblait comme si cela conduirait à beaucoup de code supplémentaire s'il est appliqué à grande échelle.

En fin de compte, la solution que j'ai installée était de créer une classe statique dans ma bibliothèque de ressources et de stocker mes messages d'exception en cela. De cette façon, il n'est pas nécessaire de les internationaliser (ce que je suis d'accord n'a pas de sens) et ils sont rendus accessibles à tout moment qu'une chaîne de ressources soit accessible puisqu'il s'agit dans la même espace de noms. (Cela convient à mon désir de ne pas faire vérifier le texte d'exception un processus complexe.)

Mon code de test se résume tout simplement à (pardon le mangling ...):

[Test, 
    ExpectedException(typeof(System.ArgumentException),
    ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
    _repository.CreateProduct("TestCreateDuplicateProduct");
    _repository.CreateProduct("TestCreateDuplicateProduct");
} 
0
Peter Bernier