Search code examples
f#nunitfsunit

FsUnit `should equal` fails on `Some []`


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?


Solution

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