2012-12-12 5 views
6

Sto provando a scrivere alcuni test NUnit in F # e ho problemi a passare una funzione allo ThrowsConstraint. Un campione distillato (non) funzionante è sotto.Come si passa una funzione a NUnit Throws Constraint?

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>()) 

Questo compila bene, ma ottengo il seguente dal test corridore NUnit:

FsTest.Tests.Example.foo: 
System.ArgumentException : The actual value must be a TestDelegate but was [email protected] 
Parameter name: actual 

Mentre io sono in grado di aggirare il problema mediante l'attributo ExpectedException, la mia domanda è che cosa è la corretta modo di usare una funzione F # in questa situazione?

risposta

7

Tutto quello che devi fare per far funzionare lo snippet originale è fissare f per avere la firma conforme a TestDelegate, che è unit -> unit. Basta scartare valore di ritorno di File.GetAttributes:

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

compilatore F # non ha barf al vostro codice originale perché solo un altro raccordo NUnit sovraccaricare Assert.That(actual: obj, expression: Constraints.IResolveConstraint) esiste.

Come Assert.That ha l'uso molto ampio mi piacerebbe restare per testare le eccezioni previste forma affermare a più specifici, ad esempio:

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

dove compilatore F # sarebbe in grado individuare staticamente la firma sbagliata della vostra funzione.

+0

Grazie mille per la spiegazione. –

+0

Bello, la sua buona soluzione, perché in F # (VS 2010) l'approccio degli attributi non funzionava per me (ho provato a marcare il metodo di prova con l'attributo ExpectedException e non ha funzionato affatto) Grazie! – Roboblob

4

IMHO, potresti risparmiare un po 'di dolore utilizzando Unquote sopra NUnit. Poi la sua affermazione sarebbe semplice come

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

grande suite di NUnit di sovraccarichi affermazione con il comportamento di runtime a volte inaspettati sono progettati per compensare la relativa mancanza di espressività rispetto al F # C# 's.

On-l'altro mano, perché F # è già dotato di caratteristiche quali il confronto strutturale asserzioni che esprimono eleganza, Unquote è progettato per sfruttare al meglio le caratteristiche native con soli tre semplici operatori di asserzione: test, raises e raisesWith.

+0

+1 per aver menzionato Unquote. –

+0

È piuttosto interessante perché l'unquote è stata la prima cosa che ho provato. Sfortunatamente la combinazione di NUnit e Unquote non ha funzionato per me, così sono tornato a NUnit. Ho riassunto il problema che avevo con NUnit e unquote e l'ho postato come una [domanda diversa] (http://stackoverflow.com/questions/13846561/missingmethodexception-when-using-unquote-asserts), il tuo aiuto con quello sarebbe essere apprezzato –

+0

Scusa @SergeBelov, è sfortunato! Ho aggiunto un commento alla tua nuova domanda. Credo che il problema che si sta avendo non sia con Unquote di per sé, ma piuttosto un problema con il caricamento/configurazione del gruppo di corridori test NUnit o qualcosa del genere. –