我有这个方法(部分方法)
public async Task<List<UserDto>> GetUsers(Guid accountId)
{
using (var context = this.contextFactory.Create())
{
var users = await context.Users
.Where(u => u.AccountId.Equals(accountId))
.Project()
.To<UserDto>()
.ToListAsync();
// I don't care about the above bit of code and whether it works
// I care about this code doing what it says it does.
if (users == null)
{
throw new Exception("there are no users");
}
}
}
所以我模拟了我的上下文工厂,我模拟了我的上下文,我模拟了DbSet
。我做了一些额外的事情:
var data = new List<User>
{
It.IsAny<User>(),
It.IsAny<User>(),
It.IsAny<User>(),
It.IsAny<User>()
};
var mockedDbSet = new Mock<IDbSet<User>>();
mockedDbSet.As<IDbAsyncEnumerable<User>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<User>(data.GetEnumerator()));
mockedDbSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<User>(data.Provider));
mockedDbSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(data.Expression);
mockedDbSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockedDbSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
这样就允许使用async
扩展方法,例如FirstOrDefaultAsync()
。但由于某种原因,即使我为它指定了映射(因为一开始抛出了错误),但现在它在尝试查询 DbSet
时抛出了空引用异常。
我只是想绕过这一部分,这样我就可以继续测试我的代码是否有效。
所以我的行为是:
Exception exception;
try
{
this.userService.GetUsers(Guid.NewGuid());
}
catch(Exception ex)
{
exception = ex;
}
我的主张:
Assert.IsNotNull(exception);
Assert.AreEqual(exception.Message, "there are no users");
那么你如何让这一切顺利进行并防止我陷入困境!
最佳答案
不要编写此测试,它没有提供任何值(value)。您仍然需要编写一个集成测试,并且该测试与 Controller 和数据源的内部实现的耦合度太高。
如果有的话,您将创建一个内存中的 DbSet stub 实现来支持对象集合。但由于这实际上并没有影响生产 LINQ 提供程序,因此您仍然需要编写集成测试,从而否定此测试所具有的任何值(value)。
简而言之,不要尝试做您在这里所做的事情,它不值得任何积极的 yield ,并且会导致对此类测试的值(value)产生错误的感觉。
关于c# - 使用Moq进行测试,一行使用异步可查询扩展和项目,如何测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27195797/