2016-10-14 1 views
2

Je fais le Diamond Kata en C# avec des tests écrits en F # en utilisant xUnit et FsCheck, et j'ai quelques problèmes en essayant de vérifier si une exception est levée dans le cas d'une entrée invalide par l'utilisateur (tout caractère qui n'est pas une lettre de l'alphabet sans signes diacritiques). Voici comment le code ressemble maintenant:Comment vérifier si une Exception est lancée par une méthode avec xUnit et FsCheck dans F #

La méthode testée:

public static string Make(char letter) 
{ 
    if (!Regex.IsMatch(letter.ToString(), @"[a-zA-Z]")) 
    { 
     throw new InvalidOperationException(); 
    } 

    // code that makes the diamond 
} 

Le test:

[<Property>] 
let ``Diamond.Make must throw an InvalidOperationException if a character that isn't 
     an alphabet letter without any diacritics is given`` (letter : char) = 
    (not (('A' <= letter && letter <= 'Z') || ('a' <= letter && letter <= 'z'))) ==> lazy 
     (Assert.Throws<InvalidOperationException>(fun() -> Diamond.Make letter |> ignore)) 

Le problème avec mon approche est que le test dit qu'aucune exception est levée, mais lorsque j'exécute l'application avec l'entrée affichée par la suite de tests, l'exception est levée.

Voici le message donné par la suite de tests (j'ai volontairement omis le nom de test et trace de la pile):

Test Outcome: Failed 
Test Duration: 0:00:00,066 
Result Message: 
FsCheck.Xunit.PropertyFailedException : 
Falsifiable, after 1 test (0 shrinks) (StdGen (1154779780,296216747)): 
Original: 
')' 
---- Assert.Throws() Failure 
Expected: typeof(System.InvalidOperationException) 
Actual: (No exception was thrown) 

Bien que la suite de tests indique que la valeur ')' aucune exception est levée, je l'ai fait un test manuel avec elle et l'exception attendue a bien été lancée.

Comment puis-je m'assurer que l'exception est détectée par le test?

+3

Veuillez envoyer le message complet d'échec de test que vous recevez. En outre, veuillez formater le code afin que le défilement ne soit pas nécessaire. –

+3

Ma conjecture est que FsCheck trouve facile de falsifier cette propriété. Il y a beaucoup de valeurs 'char' qui se situent en dehors de la plage donnée ici, par ex. 'ü' et' ø'. Ce sont toujours des lettres selon 'Char.IsLetter'. –

+1

Comprenez-vous que vous testez un Char.IsLetter maintenant? –

Répondre

4

Je pense que le problème est que Assert.Throws renvoie l'exception de type donné s'il se produit. Ignorer simplement la valeur de retour de Assert.Throws devrait vous aider.

let test (letter : char) = 
    (not (('A' <= letter && letter <= 'Z') || ('a' <= letter && letter <= 'z'))) ==> 

    lazy 
     Assert.Throws<InvalidOperationException>(fun() -> Diamond.Make letter |> ignore) 
     |> ignore 
+0

Les propriétés n'ont pas * * pour renvoyer une valeur booléenne; ils peuvent aussi retourner 'unit', ou' Property'. Pour renvoyer 'unit', rediriger le résultat de' Assert.Throws' dans 'ignore' devrait suffire. –

+0

@ MarkSeeman Vous avez raison. Je vais modifier la réponse. –

+0

De cette façon, cela a fonctionné. Merci! –