如何将函数传递给NUnit引发约束?

Ser*_*lov 9 f# interop nunit

我正在尝试在F#中编写一些NUnit测试,并且无法将函数传递给ThrowsConstraint.蒸馏(非)工作样品如下.

open System.IO
open NUnit.Framework

[<TestFixture>]
module Example =

    [<Test>]
    let foo() = 
        let f = fun () -> File.GetAttributes("non-existing.file")
        Assert.That(f, Throws.TypeOf<FileNotFoundException>())
Run Code Online (Sandbox Code Playgroud)

这编译得很好,但我从NUnit测试运行器得到以下内容:

FsTest.Tests.Example.foo:
System.ArgumentException : The actual value must be a TestDelegate but was f@11
Parameter name: actual
Run Code Online (Sandbox Code Playgroud)

虽然我能够使用ExpectedException属性解决问题,但我的问题是在这种情况下使用F#函数的正确方法是什么?

Gen*_*ski 9

您需要做的就是让原始代码段工作正在修复f以使符号符合TestDelegate,即unit -> unit.只需丢弃以下的返回值File.GetAttributes:

let f = fun () -> File.GetAttributes("non-existing.file") |> ignore
Run Code Online (Sandbox Code Playgroud)

F#编译器没有对原始代码进行barf,因为只Assert.That(actual: obj, expression: Constraints.IResolveConstraint)存在另一个适合的NUnit重载.

由于Assert.That具有非常广泛的用法,我坚持测试更具体的断言形式的预期异常,例如:

[<Test>]
let foo() =
    Assert.Throws<FileNotFoundException>
        (fun () -> File.GetAttributes("non-existing.file")|> ignore)
    |> ignore
Run Code Online (Sandbox Code Playgroud)

其中F#编译器可以静态发现函数的错误签名.