我正在尝试在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#函数的正确方法是什么?
答案 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)
[<Test>]
let foo() =
raises<FileNotFoundException> <@ File.GetAttributes("non-existing.file") @>
NUnit的大量断言重载有时会出现意外的运行时行为,旨在弥补C#与F#相比缺乏表现力。
另一方面,因为F#已经配备了诸如优雅表达断言的结构比较等功能,Unquote旨在通过三个简单的断言运算符来利用其原生特性:test
,{{ 1}}和raises
。