【发布时间】:2021-12-29 22:31:18
【问题描述】:
我有一个我想测试的方法,它有四个异步运行的方法。我想要一个单元测试来证明它们是并行运行的。我不知道该怎么做,也无法在网上找到任何东西。
这是我所拥有的一个例子
我正在尝试测试的方法
public async Task<IEnumerable<ReturnData>> GetData()
{
List<ReturnData> returnData = new List<ReturnData>();
Task<IEnumerable<ReturnData>> dataTypeA = dataServiceA.GetDataTypeA();
Task<IEnumerable<ReturnData>> dataTypeB = dataServiceB.GetDataTypeB();
Task<IEnumerable<ReturnData>> dataTypeC = dataServiceC.GetDataTypeC();
Task<IEnumerable<ReturnData>> dataTypeD = dataServiceD.GetDataTypeD();
await Task.WhenAll(dataTypeA, dataTypeB, dataTypeC, dataTypeD);
returnData.AddRange(dataTypeA.Result);
returnData.AddRange(dataTypeB.Result);
returnData.AddRange(dataTypeC.Result);
returnData.AddRange(dataTypeD.Result);
return returnData;
}
我的单元测试
[TestMethod]
public async Task GetDataTestAsync()
{
mockedDataServiceA.Setup(a => a.GetDataTypeA())
.Callback(() => Thread.Sleep(1000))
.ReturnsAsync(mockedDataA);
mockedDataServiceB.Setup(a => a.GetDataTypeB())
.Callback(() => Thread.Sleep(1000))
.ReturnsAsync(mockedDataB);
mockedDataServiceC.Setup(a => a.GetDataTypeC())
.Callback(() => Thread.Sleep(1000))
.ReturnsAsync(mockedDataC);
mockedDataServiceD.Setup(a => a.GetDataTypeD())
.Callback(() => Thread.Sleep(1000))
.ReturnsAsync(mockedDataD);
IDataService dataService = new DataService(mockedDataServiceA.Object,
mockedDataServiceB.Object,
mockedDataServiceC.Object,
mockedDataServiceD.Object,);
DateTime startTime = DateTime.Now;
IEnumerable<ReturnData> data = await dataService.GetData();
DateTime endTime = DateTime.Now;
TimeSpan timeDiff = endTime.Subtract(startTime);
Assert.IsTrue(timeDiff.TotalSeconds < 4);
}
我尝试过同时使用Thread.Sleep(1000) 和Task.Delay(1000)
两者都没有给出想要的结果。我希望测试只运行 1 秒多一点,因为每个方法都应该并行运行。
当使用Thread.Sleep(1000) 时,测试会运行 4.1 秒(测试失败)
使用Task.Delay(1000) 时,测试运行时间少于 100 毫秒。这在技术上可以通过我拥有的断言测试,但不是预期的结果。
我知道当我运行我的 Web 服务时,这些方法确实是并行运行的,我只是想要一个单元测试来证明该功能,并在将来有任何代码更改时保护该功能。
【问题讨论】:
-
在每个Task开始时设置一个bool,然后在100ms后检查是否设置了所有4个bool
-
仅供参考,您可以使用
returnData.AddRange(await Task.WhenAll(dataTypeA, dataTypeB, dataTypeC, dataTypeD));,我至少建议改为使用returnData.AddRange(await dataTypeA)。 -
使用 Task.Delay 而不是 Thread.Sleep,但不要让您的测试方法异步,而是以
var result = dataService.GetData().Wait()而不是await dataService.GetData()调用您的 GetData 方法,即保持测试方法同步。 -
@Zenilogix 我也会尝试你的建议。我确实尝试过 Task.Delay ,但没有按照您建议的方式调用该方法。我会让你知道结果。
-
@juharr 这可能在大多数情况下都有效,但我只是举例说明了我的代码是如何设置的。在我最终返回数据之前,在 .AddRange() 之后有一点代码。它与我的问题无关,因此我将其从示例代码中排除。
标签: c# unit-testing asynchronous