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

时间:2012-12-12 04:28:34

标签: 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>())

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

FsTest.Tests.Example.foo:
System.ArgumentException : The actual value must be a TestDelegate but was f@11
Parameter name: actual

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

2 个答案:

答案 0 :(得分:7)

为了让原始代码段正常运行,您需要做的就是修复f以使签名符合TestDelegate unit -> unit。只需丢弃File.GetAttributes的返回值:

let f = fun () -> File.GetAttributes("non-existing.file") |> ignore

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

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

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

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

答案 1 :(得分:4)

恕我直言,你可以在NUnit上使用Unquote来节省一些痛苦。然后你的断言就像

一样简单
[<Test>]
let foo() = 
    raises<FileNotFoundException> <@ File.GetAttributes("non-existing.file") @>

NUnit的大量断言重载有时会出现意外的运行时行为,旨在弥补C#与F#相比缺乏表现力。

另一方面,因为F#已经配备了诸如优雅表达断言的结构比较等功能,Unquote旨在通过三个简单的断言运算符来利用其原生特性:test,{{ 1}}和raises