xUnit Theory with async MemberData

时间:2018-05-04 08:00:41

标签: c# asp.net-core async-await xunit.net

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

我的测试应该专注于测试给定的DataEntry实例:DataEntry实例由我的DataService类中的异步方法GenerateData()生成,如下所示:

public class DataService {
    ...
    public async Task<List<DataEntry>> GenerateData() {
        ...
    }
    ...
}

我将这个测试用例写成一个理论,所以我的测试可以一次关注一个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 });

}

但是,我在编译时遇到以下错误:

  

MemberData必须引用可分配给“System.Collections.Generic.IEnumerable&lt; object []&gt;”的数据类型。引用的类型'System.Threading.Tasks.Task&lt; System.Collections.Generic.IEnumerable&lt; object []&gt;&gt;'无效。

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

现在,我知道我可以将我的理论转换为事实并循环遍历我的DataService返回的列表中的每个DataEntry,但是我更喜欢保持理论设置,因为我的测试会更清洁并专注于DataEntry而不是List&lt ;&的DataEntry GT;

问题xUnit.net中是否有办法让我的理论从我的DataService异步API中获取数据?请注意,不能更改或扩展DataService类以同步提供数据。

修改

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

2 个答案:

答案 0 :(得分:0)

在 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]);
    }
}

答案 1 :(得分:0)

内部不提供此功能。您可以尝试以下操作:

  1. 通过继承 DataAttribute 编写您的 CustomMemberDataAttribute
  2. 覆盖父类的“GetData”方法。
  3. 使方法异步,即提供数据。
  4. 从“GetData”方法调用异步数据提供程序方法。
  5. 使用您的 CustomMemberDataAttribute 来装饰测试用例。

您可以参考以下链接来编写您的自定义属性。 保持其他方法不变,只需修改上面讨论的“GetData”方法。 https://github.com/xunit/xunit/blob/bccfcccf26b2c63c90573fe1a17e6572882ef39c/src/xunit.core/MemberDataAttributeBase.cs