39 votes

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

Visual Studio Test peut vérifier les exceptions attendues en utilisant l'attribut ExpectedException. Vous pouvez transmettre une exception comme ceci :

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

Vous pouvez également vérifier le message contenu dans l'ExpectedException comme ceci :

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

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

[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, expression typeof ou une expression de création de tableau d'un attribut

Quelqu'un sait-il comment tester une exception dont le message provient d'un fichier de ressources ?


Une option que j'ai envisagée est l'utilisation de classes d'exceptions personnalisées, mais en me basant sur des conseils souvent entendus tels que :

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

Je ne m'attends pas à traiter les exceptions différemment dans le flux normal (il s'agit d'une exception critique, donc je passe en mode panique de toute façon) et je ne pense pas que créer une exception pour chaque cas de test soit la bonne chose à faire. Un avis ?

63voto

Daniel Plaisted Points 11183

Je recommanderais d'utiliser une méthode d'aide au lieu d'un attribut. Quelque chose comme ceci :

public static class ExceptionAssert
{
  public static T Throws<T>(Action action) where T : Exception
  {
    try
    {
      action();
    }
    catch (T ex)
    {
      return ex;
    }
    Assert.Fail("Exception of type {0} should be thrown.", typeof(T));

    //  The compiler doesn't know that Assert.Fail
    //  will always throw an exception
    return null;
  }
}

Vous pouvez alors écrire votre test comme ceci :

[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
  OrganizationList organizations = new Organizations();
  organizations.Add(new Organization());
  organizations.Add(new Organization());

  var ex = ExceptionAssert.Throws<CriticalException>(
              () => organizations.GetOrganization());
  Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}

Cela présente également l'avantage de vérifier que l'exception est levée à la ligne où vous vous attendiez à ce qu'elle soit levée et non pas n'importe où dans votre méthode de test.

14voto

user53794 Points 2347

L'argument ExpectedException Message ne correspond pas au message de l'exception. Il s'agit plutôt du message qui est imprimé dans les résultats du test si l'exception attendue ne s'est pas produite.

7voto

Simon Buchan Points 6245

Juste une opinion, mais je dirais que le texte d'erreur :

  • fait partie du test, auquel cas l'obtenir à partir de la ressource serait 'faux' (sinon vous pourriez vous retrouver avec une ressource constamment tronquée), donc mettez simplement à jour le test lorsque vous changez la ressource (ou que le test échoue).
  • ne fait pas partie du test, et vous devriez seulement vous soucier du fait qu'il lève l'exception.

Notez que la première option devrait vous permettre de tester plusieurs langues, étant donné la possibilité de fonctionner avec une locale.

En ce qui concerne les exceptions multiples, je viens du pays du C++, où la création d'un grand nombre d'exceptions (au point d'en créer une par instruction 'throw' !) dans de grandes héritières est acceptable (voire courante), mais le système de métadonnées de .Net n'aime probablement pas cela, d'où ce conseil.

4voto

cruizer Points 4821

Je pense que vous pouvez simplement faire un try-catch explicite dans votre code de test au lieu de compter sur l'attribut ExpectedException pour le faire à votre place. Ensuite, vous pouvez trouver une méthode d'aide qui lira le fichier de ressources et comparera le message d'erreur à celui qui accompagne l'exception qui a été attrapée. (Bien entendu, s'il n'y a pas eu d'exception, le scénario de test doit être considéré comme un échec).

3voto

Jedidja Points 5642

Si vous passez à l'utilisation de la très belle xUnit.Net vous pouvez remplacer [ExpectedException] par quelque chose comme ceci :

[Fact]
public void TestException()
{
   Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
   // Assert whatever you like about the exception here.
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X