Kir*_*rzy -1 c# nunit async-await
我有这个代码
public class ClassToTest
{
private readonly IRepository repository;
public ClassToTest(DI GOES HERE){...}
public DoSomething()
{
Task.Run(async () => {
//some code
repository.ExecuteAsync();
}
}
}
public class Repository : IRepository
{
public Task ExecuteAsync()
{
using (var connection = new SqlConnection(DbConfiguration.DatabaseConnection))
{
return connection.ExecuteAsync(storedProcedure, parameters, commandType: CommandType.StoredProcedure, commandTimeout: Configuration.TransactionTimeout);
}
}
}
[Test]
public void TestMethod()
{
var repository = new Mock<IRepository>;
var classToTest = new ClassToTest();
classToTest.DoSomething();
repository.Veryfy(p => p.ExecuteAsync(), Times.Once());
}
Run Code Online (Sandbox Code Playgroud)
测试失败并显示此消息
模拟一次的预期调用,但是是0次:p => p.ExecuteAsync()
有谁知道为什么?
谢谢
正如其他人所提到的那样,因为您正在调用Task.Run而不是等待响应,所以单元测试可能会在后台任务开始之前完成,因此Moq验证失败.
此外,您的代码将不会按原样编译 - 当在StackOverflow上询问Q时,请务必提供完整的,可编译的MVP.
特别重要的是您要测试的代码中的错误.在范围内Repository.ExecuteAsync调用connection.ExecuteAsync,using但这是不等的.这意味着将在任务完成之前处理连接.您需要将方法更改为async和await延迟处理连接的调用.
但是,包装方法DoSomething方法不应该使用Task.Run(),因为它没有为存储库任务添加任何值,也不需要重复async / return await它.
然后调用者(在这种情况下你的单元测试)等待DoSomething(或者如果调用者真的想要在不等待任务的情况下进行进一步处理,则将其留给调用者来决定.至少这样,调用者得到一个句柄任务,检查完成情况).
代码的最终状态可能看起来更像是:
public class ClassToTest
{
private readonly IRepository _repository;
public ClassToTest(IRepository repository)
{
_repository = repository;
}
// Doesn't necessarily need to be async
public Task DoSomething()
{
// We're return the wrapped task directly, and adding no additional value.
return repository.ExecuteAsync();
}
}
public class Repository : IRepository
{
public async Task ExecuteAsync()
{
using (var connection = new SqlConnection(DbConfiguration.DatabaseConnection))
{
// Here we do need to await, otherwise we'll dispose the connection
return await connection.ExecuteAsync(storedProcedure, parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: Configuration.TransactionTimeout);
}
}
}
// NUnit has full support for async / await
[Test]
public async Task TestMethod()
{
var repository = new Mock<IRepository>();
var classToTest = new ClassToTest(repository.Object);
repository.Setup(_ => _.ExecuteAsync()).Returns(Task.FromResult((object)null));
// Moq also has support for async, e.g. .ReturnsAsync
// You need to await the test.
await classToTest.DoSomething();
repository.Verify(p => p.ExecuteAsync(), Times.Once());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
548 次 |
| 最近记录: |