5

I have started to use F# Expecto framework and cannot find a proper way to assert for an exception in async computation expressions.

My code ended up with:

Expect.throws (fun () ->
    async {
        // Some async code expected to fail...
        do! Async.Sleep 1
        failwith "error"
    }
    |> Async.RunSynchronously
    |> ignore) "valuable message"

Is there a better way to do this? (without RunSynchronously and ignore).

Thanks

ded'
  • 664
  • 4
  • 11
  • 1
    I've opened a PR to add some utility functions for this: https://github.com/haf/expecto/pull/469 – Jwosty Aug 08 '23 at 22:33

1 Answers1

0

A combinator for this doesn't seem to be built into Expecto yet, but you can extend it with your own:

module Expect =
    let throwsAsync (code: unit -> Async<unit>) (message: string) = async {
        let! thrown = async {
            // Using a try-catch and a lambda is better than Async.Catch, because there are otherwise some circumstances where exceptions don't get caught
            try
                //
                do! code ()
                return false
            with _ ->
                return true
        }
        if not thrown then
            failtestf "%s. Expected f to throw." message
    }

Then use it like so:

let f () = async {
    // Some async code expected to fail...
    do! Async.Sleep 1
    failwith "error"
}

testCaseAsync "Some test" (async {
    do! Expect.throwsAsync (fun () -> f ()) "Should throw"
})
Jwosty
  • 3,497
  • 2
  • 22
  • 50