Chciałbym przetestować następujące obieg asynchronicznej (z NUnit + FsUnit):Jak uzyskać użyteczną StackTrace podczas testowania F # async przepływy pracy
let foo = async {
failwith "oops"
return 42
}
napisałem następujący test dla niego:
let [<Test>] TestFoo() =
foo
|> Async.RunSynchronously
|> should equal 42
Ponieważ foo rzuca się następujący stackTrace w biegacza testów jednostkowych:
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
Niestety dOE stackTrace powiedz mi, gdzie został zgłoszony wyjątek. Zatrzymuje się w RunSynchronously.
Gdzieś słyszałem, że Async.Catch magicznie przywraca StackTrace, więc poprawiłem 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))
teraz jest brzydki, ale przynajmniej produkuje użytecznej 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 Microsoft.FSharp.Control.AsyncBuilderImpl.[email protected](AsyncParams`1 args)
ten czas pokazania stosu pokazuje dokładnie, gdzie wystąpił błąd: [email protected] 71
Czy istnieje sposób na pozbycie się Async.Catch i dopasowanie dwóch opcji wciąż otrzymując przydatne stosy stacków? Czy istnieje lepszy sposób na uporządkowanie asynchronicznych testów przepływu pracy?
Miałem ten sam problem i Async.Złapałem jedyne obejście, jakie mogłem znaleźć. –
Mam emaila do Dona Syme'a, który zasugerował, że było to podstawowe ograniczenie .NET, a opcja 'Async.Catch' była jedyną opcją. –
@JohnPalmer brzmi jak odpowiedź na mnie – mydogisbox