mi piacerebbe provare il seguente flusso di lavoro asincrona (con NUnit + FsUnit):Come ottenere un utile stacktrace durante il test F # async flussi di lavoro
let foo = async {
failwith "oops"
return 42
}
ho scritto il seguente test per esso:
let [<Test>] TestFoo() =
foo
|> Async.RunSynchronously
|> should equal 42
Da pippo getta ottengo il seguente stackTrace nella unit test runner:
System.Exception : oops
at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
at ExplorationTests.TestFoo() in ExplorationTests.fs: line 76
Purtroppo la cerva stacktrace non dirmi dove è stata sollevata l'eccezione. Si ferma su RunSynchronously.
Da qualche parte ho sentito che Async.Catch ripristina magicamente lo stacktrace, così ho adattato il mio test:
let [<Test>] TestFooWithBetterStacktrace() =
foo
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
| Choice1Of2 x -> x |> should equal 42
| Choice2Of2 ex -> raise (new System.Exception(null, ex))
Ora, questo è brutto, ma almeno produce un utile stacktrace:
System.Exception : Exception of type 'System.Exception' was thrown.
----> System.Exception : oops
at Microsoft.FSharp.Core.Operators.Raise(Exception exn)
at ExplorationTests.TestFooWithBetterStacktrace() in ExplorationTests.fs: line 86
--Exception
at Microsoft.FSharp.Core.Operators.FailWith(String message)
at [email protected](Unit unitVar) in ExplorationTests.fs: line 71
at [email protected](AsyncParams`1 args)
Questo time lo stacktrace mostra esattamente dove si è verificato l'errore: [email protected] 71
C'è un modo per sbarazzarsi di Async.Catch e l'abbinamento tra due scelte pur ottenendo ancora utili stacktraces? C'è un modo migliore per strutturare i test del flusso di lavoro asincrono?
Ho avuto lo stesso problema e Async.Catch è stata l'unica soluzione alternativa che ho trovato –
Ho inviato un'email a Don Syme, il quale ha suggerito che si trattava di una limitazione .NET fondamentale e che "Async.Catch" era l'unica opzione. –
@JohnPalmer mi suona come una risposta – mydogisbox