我有这种方法(部分方法)
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");
那么你如何才能让这一切发挥得更好,防止我陷入困境!
答案 0 :(得分:3)
不要写这个测试,它没有提供任何价值。您仍然在编写集成测试,并且此测试与控制器和数据源的内部实现相结合。
如果有的话,您可以创建一个支持对象集合的内存中DbSet存根实现。但是,由于这实际上并没有触及生产LINQ提供程序,因此您仍然可以编写集成测试,否定此测试所具有的任何价值。
简而言之,不要尝试做你在这里做的事情,它不值得任何积极的收获,并导致这种测试的错误价值。
答案 1 :(得分:0)
事实证明
var data = new List<User>
{
It.IsAny<User>(),
It.IsAny<User>(),
It.IsAny<User>(),
It.IsAny<User>()
};
使我的.Project()
查询返回null引用异常。只需使用new User()
即可轻松解决此问题。