【问题标题】:FsUnit `should equal` fails on `Some []`FsUnit `should equal` 在 `Some []` 上失败
【发布时间】:2014-06-02 17:21:24
【问题描述】:

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

【问题讨论】:

  • 这看起来像 FsUnit 修改了 = 的语义 - 运行等效代码但使用 = 而不是 should equal 返回您所期望的。
  • stackoverflow.com/questions/5667372/… - 取消引用总是符合我的意思,除此之外还有更多

标签: f# nunit fsunit


【解决方案1】:

原因是 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)

【讨论】:

【解决方案2】:

这是因为您的两个空列表属于不同类型。在这个版本的测试中查看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>)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多