5

当我使用 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 相同,测试也会失败。发生了什么?

4

2 回答 2

9

原因是 FsUnit 在底层使用了无类型机制,因此由类型检查器Expected推断object(参见Object y堆栈跟踪中的部分)。

一种解决方法是为泛型值添加类型注释,即

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

有几个人被这种情况所困扰,例如类型提供程序中的 Weird None 行为

一旦它们不再是类型安全的,流利断言的美对我来说就毫无意义了。我建议创建一个类型安全的替代方案

let shouldEqual (x: 'a) (y: 'a) = 
    Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y)
于 2014-06-02T09:21:24.423 回答
4

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

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

expectedis'a list option和实际 is int list option,所以它们不相等。

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

[<Test>]
let test() =
  f []
  |> should equal (Some List.empty<int>)
于 2014-06-02T09:16:13.090 回答