2

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?

4

1 回答 1

5

我认为问题在于 Assert.Throws 如果发生则返回给定类型的异常。只是忽略 Assert.Throws 的返回值应该对您有所帮助。

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

    lazy
        Assert.Throws<InvalidOperationException>(fun () -> Diamond.Make letter |> ignore)
        |> ignore
于 2016-10-14T20:54:24.597 回答