问题
When I run this FsUnit test with NUnit 2.6.3,
let f xs = Some (List.map ((+) 2) xs)
[<Test>]
let test() =
f []
|> should equal (Some [])
I get:
Result Message:
Expected: <Some([])>
But was: <Some([])>
Result StackTrace:
at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object y)
The test fails even though the Expected and Actual in the message are the same. What happened?
回答1:
The reason is that FsUnit uses untyped mechanism under the hood so Expected
is inferred as object
by the type checker (see the Object y
part in the stacktrace).
A workaround is to add type annotation for generic values i.e.
[<Test>]
let test() =
f []
|> should equal (Some ([]: int list))
Several people have been bitten by this e.g. Weird None behaviour in type providers.
Beauty of fluent assertions is pointless to me once they're no longer type-safe. I suggest to create a type-safe alternative:
let shouldEqual (x: 'a) (y: 'a) =
Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y)
回答2:
This is because your two empty lists are of different types. See the types of actual
and expected
in this version of your test:
[<Test>]
let test() =
let expected = Some []
let actual = f []
actual |> should equal expected
expected
is 'a list option
and actual is int list option
, so they are not equal.
If you give the compiler some hints about the expected result then it will work.
[<Test>]
let test() =
f []
|> should equal (Some List.empty<int>)
来源:https://stackoverflow.com/questions/23989847/fsunit-should-equal-fails-on-some