具有异步MemberData的xUnit理论

smn*_*ino 6 c# xunit.net async-await asp.net-core

我有一个使用xUnit.net v.2.3.1的ASP.NET Core 2.0 Web应用程序的单元测试项目。

我的测试应集中在测试给定的DataEntry实例上:DataEntry实例由DataService类中的async方法GenerateData()生成,如下所示:

public class DataService {
    ...
    public async Task<List<DataEntry>> GenerateData() {
        ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我将此测试用例写为Theory,因此我的测试可以一次集中在DataEntry实例上。这是代码:

[Theory]
[MemberData(nameof(GetDataEntries))]
public void Test_DataEntry(DataEntry entry) {

    // my assertions
    Assert.NotNull(entry);
    ...

}

public static async Task<IEnumerable<object[]>> GetDataEntries() {

    var service = new DataService();
    List<DataEntry> entries = await service.GenerateData().ConfigureAwait(false);

    return entries.Select(e => new object[] { e });

}
Run Code Online (Sandbox Code Playgroud)

但是,在编译时出现以下错误:

MemberData必须引用可分配给'System.Collections.Generic.IEnumerable <object []>'的数据类型。引用的类型'System.Threading.Tasks.Task <System.Collections.Generic.IEnumerable <object [] >>'是无效的。

从错误描述来看,似乎xUnit.net不允许MemberData使用异步静态方法,例如我的GetDataEntries()。我应该注意xUnit.net中是否存在功能差距?

现在,我知道可以将我的理论转换为事实并遍历DataService返回的列表中的每个DataEntry,但是我希望保留Theory的设置,因为我的测试将更加简洁并专注于DataEntry而不是List <DataEntry> 。

问题xUnit.net中有什么方法可以让我的Theory从我的DataService异步API获取数据?请注意,不能更改或扩展DataService类以同步提供数据。

编辑

我正在寻找一种通过async / await的方法,并且希望避免在我的GenerateData()方法上使用任何诸如Task <T> .Result之类的阻塞调用,因为底层线程将被阻塞直到操作完成。这与我的测试项目有关,因为我还有其他类似的测试用例,在这些用例中,应以相同的方式检索数据,因此,我希望避免以太多的阻塞调用而告终,而是保持异步/等待传播。

Jos*_*lva 2

在 xUnit 允许异步理论数据之前,您可以使用Task<T>实例作为理论数据并在测试方法中等待它们(请注意,测试方法可以是异步的):

public static IEnumerable<object> GetDataEntries() {
    var service = new DataService();
    yield return new object[] { service.GenerateData() };
}

[Theory]
[MemberData(nameof(GetDataEntries))]
public async Task Test_DataEntry(Task<List<DataEntry>> task) {
    List<DataEntry> entries = await task;

    for (int i = 0; i < entries.Count; i++) {
        // my assertions
        Assert.NotNull(entries[i]);
    }
}
Run Code Online (Sandbox Code Playgroud)