【问题标题】:How do I write an async unit test method in F#如何在 F# 中编写异步单元测试方法
【发布时间】:2017-09-14 20:27:02
【问题描述】:

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

我引用了以下code

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

这是我失败的尝试:

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

        SystemUnderTest.FailAsync() | Async.RunSynchronously
    }

【问题讨论】:

  • 这是使用 NUnit 吗?
  • 是的。我正在使用 NUnit。
  • 您是否尝试过简单地删除async { } 并使测试同步?即SystemUnderTest.FailAsync() |&gt; Async.AwaitIAsyncResult |&gt; Async.RunSynchronously,就是这样。或者,如果同步测试不符合您的要求,并且测试必须是异步的,那么我建议您查看Expecto,其中异步测试是常态而不是例外。跨度>

标签: unit-testing f# async-await


【解决方案1】:

所以经过一番研究,事实证明这比想象的要困难。 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
  }

对不起,如果这不是最令人满意的答案。

【讨论】:

  • 我尝试了您提供的 XUnit 示例并收到以下错误:
  • 错误 FS0001 此表达式的类型应为“Async”,但此处的类型为“System.Threading.Tasks.Task
  • 我将您的 XUnit 示例应用于:做! Async.AwaitTask(someAsyncCall())|> Async.Ignore
【解决方案2】:
open Xunit

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

【讨论】:

    【解决方案3】:

    我问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 {
        }
    

    【讨论】:

      【解决方案4】:

      这是一个老问题,但现在可以使用 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 ()
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-14
        • 1970-01-01
        • 1970-01-01
        • 2016-03-26
        • 1970-01-01
        相关资源
        最近更新 更多