如何在F#中编写异步单元测试方法

时间:2017-09-14 20:27:02

标签: unit-testing f# async-await

如何在F#中编写异步测试方法?

我引用了以下code

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

这是我失败的尝试:

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

        SystemUnderTest.FailAsync() | Async.RunSynchronously
    }

4 个答案:

答案 0 :(得分:3)

经过一番研究后发现,这比应该的更难。 https://github.com/nunit/nunit/issues/34

据说有人提到了一种解决方法。这看起来有点蹩脚但是,它看起来像宣布一个任务代表作为成员外部并利用它是一个可行的工作。

主题中提到的例子:

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

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遇到了类似的问题,并提出了一个解决方案: https://github.com/xunit/xunit/issues/955

所以你应该能够在xunit

中做到这一点
[<Fact>]
let ``my async test``() =
  async {
    let! x = someAsyncCall()
    AssertOnX
  }

很抱歉,如果这不是最令人满意的答案。

答案 1 :(得分:2)

open Xunit

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

答案 2 :(得分:0)

我问https://github.com/fsprojects/FsUnit/issues/153是因为我认为F#单元测试框架有责任提供正确的绑定。 同时,这对我来说是最好的。

    open System.Threading.Tasks

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

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

答案 3 :(得分:0)

这是一个老问题,但现在可以使用 Ply 包中的 task 构建器在 Xunit 中测试 C# 异步方法,如下所示:

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