简体   繁体   中英

How do I write an async unit test method in F#

How do I write an async test method in F#?

I'm referencing the following code :

[TestMethod]
public async Task CorrectlyFailingTest()
{
  await SystemUnderTest.FailAsync();
}

This is my failed attempt:

[<Test>]
let ``Correctly failing test``() = async {

        SystemUnderTest.FailAsync() | Async.RunSynchronously
    }

So after a bit of research, it turns out that this is more difficult than it ought to be. https://github.com/nunit/nunit/issues/34

That being said a workaround was mentioned. This seems kinda lame but, it looks like declaring a task delegate outside as a member and leveraging it is a viable work around.

The examples mentioned in the thread:

open System.Threading.Tasks
open System.Runtime.CompilerServices

let toTask computation : Task = Async.StartAsTask computation :> _

[<Test>]
[<AsyncStateMachine(typeof<Task>)>]
member x.``Test``() = toTask <| async {
    do! asyncStuff()
}

And

open System.Threading.Tasks
open NUnit.Framework

let toAsyncTestDelegate computation = 
    new AsyncTestDelegate(fun () -> Async.StartAsTask computation :> Task)

[<Test>]
member x.``TestWithNUnit``() = 
    Assert.ThrowsAsync<InvalidOperationException>(asyncStuff 123 |> toAsyncTestDelegate)
    |> ignore

[<Test>]
member x.``TestWithFsUnit``() = 
    asyncStuff 123 
    |> toAsyncTestDelegate
    |> should throw typeof<InvalidOperationException>

XUnit had a similar problem and did come up with a solution: https://github.com/xunit/xunit/issues/955

So you should be able to do this in xunit

[<Fact>]
let ``my async test``() =
  async {
    let! x = someAsyncCall()
    AssertOnX
  }

Sorry if this is not the most satisfying answer.

open Xunit

[<Fact>]
let ``my async test``() =
  async {
    do! Async.AwaitTask(someAsyncCall())|> Async.Ignore
    AssertOnX
  }

I asked https://github.com/fsprojects/FsUnit/issues/153 because I think that it is a responsibility of the F# unit testing framework to provide a right binding. Meanwhile, this looks the best for me.

    open System.Threading.Tasks

    let runAsyncTest async = async |> Async.StartImmediateAsTask :> Task

    [<Test>]
    let ``Some test`` () = runAsyncTest <| async {
    }

This is an old question but now can use the task builder from the Ply package for testing C# async methods in Xunit like so:

    open FSharp.Control.Tasks
    open System.Threading
    open Xunit
    
    let ``Test some Task returning async method`` () =
        task {
            let! actual = MyType.GetSomethingAsync()
            Assert.Equal(expected, actual)
            
            return ()
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM