10

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#関数を使用する正しい方法は何ですか?

4

2 に答える 2

10

元のスニペットが機能するために必要なことは、f署名が に準拠するように修正することだけTestDelegateですunit -> unit。の戻り値を破棄するだけですFile.GetAttributes:

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

別の適切な NUnit オーバーロードAssert.That(actual: obj, expression: Constraints.IResolveConstraint)が存在するため、F# コンパイラは元のコードにバーフしませんでした。

非常に幅広い用途があるためAssert.That、より具体的な assert フォームに対して予想される例外をテストするために固執します。たとえば、次のようになります。

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

F# コンパイラは、関数の間違った署名を静的に見つけることができます。

于 2012-12-12T05:01:48.310 に答える
4

私見ですが、NUnit の上でUnquoteを使用することで、多少の負担を軽減できます。次に、あなたの主張は次のように簡単になります

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

NUnit のアサーション オーバーロードの大規模なスイートは、予期しない実行時の動作を伴う場合があり、F# と比較して C# の相対的な表現力の欠如を補うように設計されています。

一方、F# にはアサーションをエレガントに表現するための構造比較などの機能が既に備わっているため、Unquote はtestraises、およびの 3 つの単純なアサーション演算子だけでネイティブ機能を活用するように設計されていますraisesWith

于 2012-12-12T14:15:42.577 に答える