使用Moq进行测试,一行使用异步可查询扩展和项目,如何测试

时间:2014-11-28 20:57:25

标签: c# unit-testing moq automapper

我有这种方法(部分方法)

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");

那么你如何才能让这一切发挥得更好,防止我陷入困境!

2 个答案:

答案 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()即可轻松解决此问题。