Liordino Neto
Liordino Neto

Reputation: 59

How to check if an Exception is thrown by a method with xUnit and FsCheck in F#

I'm doing the Diamond Kata in C# with tests writen in F# using xUnit and FsCheck, and I'm having some trouble when trying to check if an Exception is thrown in case of a invalid input by the user (any char that isn't an alphabet letter without any diacritics). Here's how the code looks like now:

The method being tested:

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

    // code that makes the diamond
}

The 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))

The problem with my approach is that the test says that no Exception is thrown, but when I run the application with the input shown by the test suite the exception is raised.

Here is the message given by the test suite (I have intentionally omitted the test name and stack trace):

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)

Although the test suite says that for the value ')' no exception is thrown, I did a manual test with it and the expected exception was indeed thrown.

How can I make sure that the Exception is caught by the test?

Upvotes: 2

Views: 1462

Answers (1)

Antti Lepp&#228;nen
Antti Lepp&#228;nen

Reputation: 373

I think the problem is that Assert.Throws returns exception of given type if it occurs. Just ignoring return value of Assert.Throws should help you.

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

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

Upvotes: 5

Related Questions