FsUnit`应该等于`失败了`Some []`

时间:2014-06-02 08:02:42

标签: f# nunit fsunit

当我使用NUnit 2.6.3运行此FsUnit测试时,

let f xs = Some (List.map ((+) 2) xs)

[<Test>]
let test() =
  f []
  |> should equal (Some [])

我明白了:

Result Message: 
Expected: <Some([])>
  But was:  <Some([])>
Result StackTrace:  
at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object y)

即使消息中的Expected和Actual相同,测试也会失败。发生了什么事?

2 个答案:

答案 0 :(得分:8)

原因是FsUnit使用了无类型机制,因此类型检查器会将Expected推断为object(请参阅堆栈跟踪中的Object y部分)。

解决方法是为通用值添加类型注释,即

[<Test>]
let test() =
  f []
  |> should equal (Some ([]: int list))

有几个人被这种情况所困扰,例如Weird None behaviour in type providers

一旦他们不再是类型安全的,流畅的断言之美对我来说毫无意义。我建议创建type-safe alternative

let shouldEqual (x: 'a) (y: 'a) = 
    Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y)

答案 1 :(得分:4)

这是因为您的两个空列表属于不同类型。在此版本的测试中查看actualexpected的类型:

[<Test>]
let test() =
  let expected = Some []
  let actual = f []
  actual |> should equal expected

expected'a list option,实际为int list option,因此它们不相等。

如果你给编译器一些关于预期结果的提示,那么它将起作用。

[<Test>]
let test() =
  f []
  |> should equal (Some List.empty<int>)