如何断言预期会出现异常

neo*_*pir 4 f# .net-core expecto

我在使用 .NET Core 2.0 运行 F# 的 Mac 上。

我有一个如下所示的函数:

let rec evaluate(x: string) =
  match x with
  // ... cases
  | _ -> failwith "illogical"
Run Code Online (Sandbox Code Playgroud)

我想编写一个 Expecto 测试来验证异常是否按预期抛出,大致如下:

// doesn't compile
testCase "non-logic" <| fun _ ->
  Expect.throws (evaluate "Kirkspeak") "illogical" 
Run Code Online (Sandbox Code Playgroud)

错误是

该表达式的类型应为“unit -> unit”,但这里的类型为“char”

unit -> unit让我这类似于Assert.Fail,这不是我想要的。

由于对 F# 和 Expecto 有点陌生,我无法找到断言异常按预期抛出的工作示例。有人有吗?

gfr*_*itz 6

Expect.throws具有签名(unit -> unit) -> string -> unit,因此您要测试的函数必须是 (unit -> unit) 或包装在 (unit -> unit) 函数内。

let rec evaluate (x: string) : char =
  match x with
  // ... cases
  | _ -> failwith "illogical"
Run Code Online (Sandbox Code Playgroud)

编译器错误告诉您传递给 Expect.throws 的函数尚不具有正确的签名。

[<Tests>]
let tests = testList "samples" [
    test "non-logic" {
      // (evaluate "Kirkspeak") is (string -> char)
      // but expecto wants (unit -> unit)
      Expect.throws (evaluate "Kirkspeak") "illogical"
    }
]

[<EntryPoint>]
let main argv =
    Tests.runTestsInAssembly defaultConfig argv
Run Code Online (Sandbox Code Playgroud)

使其发挥作用的一种方法是改变

Expect.throws (evaluate "Kirkspeak") "illogical"
Run Code Online (Sandbox Code Playgroud)

// you could instead do (fun () -> ...)
// but one use of _ as a parameter is for when you don't care about the argument
// the compiler will infer _ to be unit
Expect.throws (fun _ -> evaluate "Kirkspeak" |> ignore) "illogical"
Run Code Online (Sandbox Code Playgroud)

现在expecto很高兴!

Expecto 表示断言异常抛出的测试通过

这个答案是我思考的方式。遵循类型签名通常很有帮助。

编辑:我看到你的错误消息,This expression was expected to have type 'unit -> unit' but here has type 'char'所以我更新了我的答案以匹配它。

  • 真奇怪。我从 netcoreapp2.0 控制台项目中提取了在答案中放入的所有代码。您收到进一步的消息了吗? (2认同)