使用FsUnit.Xunit断言异常消息时遇编译错误求助
解决FsUnit.Xunit中
throwWithMessage的类型不匹配错误 嘿,我之前也踩过这个坑!你遇到的FS0001类型错误,核心原因是对throwWithMessage的调用方式理解错了——它和throw的用法不一样,不是直接替换就行的。
先看错误本质:throw是直接接收一个抛出异常的函数(类型是(unit -> unit) -> 'a),但throwWithMessage是个柯里化函数,得先传入异常消息的匹配规则,它才会返回一个和throw同类型的断言函数。如果直接像用throw那样写,编译器就会因为参数不匹配报错。
正确用法示例
先看你可能写错的错误写法:
// ❌ 错误写法:直接替换throw,导致类型不匹配 (fun () -> failwith "test error") |> should throwWithMessage "test error"
改成下面的正确写法就行,关键是把throwWithMessage "test error"用括号括起来,作为整体传给should:
// ✅ 正确写法 (fun () -> failwith "test error") |> should (throwWithMessage "test error")
如果还要指定特定的异常类型,比如InvalidOperationException,可以这样写:
open FsUnit.Xunit open Xunit [<Fact>] let ``verify exception type and message`` () = let faultyFunc () = raise (InvalidOperationException("Oops, invalid operation!")) // 方式1:传入typeof获取类型 faultyFunc |> should (throwWithMessage typeof<InvalidOperationException> "Oops, invalid operation!") // 方式2:用泛型更简洁 faultyFunc |> should (throwWithMessage<InvalidOperationException> "Oops, invalid operation!")
为什么会报错?
再拆解下类型:
throw的签名是:(unit -> unit) -> 'a,直接接收异常函数就能断言throwWithMessage的签名是:string -> (unit -> unit) -> 'a(带类型的版本是Type -> string -> (unit -> unit) -> 'a),它需要先接收消息,返回一个和throw同类型的函数,再接收异常函数。
所以不加括号的话,编译器会把throwWithMessage和"test error"当成两个独立参数传给should,自然就会报类型不兼容的错误啦。
内容的提问来源于stack exchange,提问作者jasper
相关产品推荐
相关产品推荐

