我在netcoreapp2.2 .net核心测试项目中的测试遇到问题。
在测试开始之前,我需要获取一些将在测试之间共享的数据。
但是,从命令行运行以下测试时,它将挂起。 像这样执行测试:
dotnet test --filter "Test async initialization"
错误代码如下:
let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
let luke =
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
如果我像这样将HttpClient的创建放入luke提取程序中,它将起作用:
let luke =
let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
这意味着我无法在不同的提取程序之间共享相同的HttpClient。
任何人都知道发生了什么,以及如何在多个功能之间共享同一客户端?
答案 0 :(得分:2)
引起此问题的原因是“初始化”代码不是真正的初始化代码。这些只是两个静态字段,只有在请求时才会对其进行评估。如果您调试单元测试,您将看到c
和luke
仅在执行到达第
Assert.NotNull(luke)
如果使用类似JustDecompile的反编译器,则会看到模块的代码位于名为Tests$
的静态类中,该类的静态构造函数将初始化其自己的c
和luke
属性。 Test async initialization
放在Tests
类中,它具有自己的c
和luke
属性,这些属性委派给Tests$
类。
长话短说,直到请求luke
的值之前,“初始化”代码都不会运行。我不知道为什么这最终会阻止测试,很可能与测试运行程序发生冲突。初始化代码不在初始化时运行就足够了。
要使初始化代码在应有的时间运行,可以使用“经典”测试类型:
namespace MyTests
open System
open Xunit
open System.Net.Http
open Xunit.Abstractions
type Tests() =
static let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
static let luke =
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
static do
//Pity we can't actually print here
printfn "Even more initialization!"
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
在这种情况下,静态绑定应按其应在任何测试之前执行,并且代码不会阻塞。初始化只会发生一次。
对于capture output,测试类构造函数应接受ITestOutputHelper参数。现在有了测试类,这很容易做到:
type Tests(output:ITestOutputHelper) =
...
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
output.WriteLine "It worked!"
每次测试初始化应放在do
块中:
type Tests(output:ITestOutputHelper) =
do
output.WriteLine "This prints before each test"