尝试模拟时,源IQueryable没有实现IDbAsyncEnumerable

时间:2018-09-04 09:30:04

标签: c# entity-framework unit-testing nunit moq

我正在尝试测试我拥有的一些代码:

public async Task<Sortation> SaveAsync(Sortation sortation)
{
    if (sortation.Id == 0)
    {
        var sortations = await ListAsync(sortation.CategoryId);
        sortation.Order = sortations.Count;
        _sortationService.Create(sortation);
    }
    else
    {
        _sortationService.Update(sortation);
    }

    await _sortationService.SaveChangesAsync();

    return sortation;
}

ListAsync 方法导致我遇到问题。 我这样设置测试:

[Test]
public async Task ShouldHaveOrderOfZero()
{
    // Assemble
    const string categoryId = "cameras";
    var services = SortationContext.GivenServices();
    var sortationProvider = services.WhenGetSortationProvider();
    var sortations = new List<Sortation>();
    var sortation = new Sortation { CategoryId = categoryId };

    services.MockSortationService.Setup(x => x.List()).Returns(sortations.AsQueryable);

    // Act
    await sortationProvider.SaveAsync(sortation);

    // Assert
    sortation.Order.Should().Be(0);
}

运行此命令时,出现此错误:

  

消息:System.InvalidOperationException:源IQueryable没有实现IDbAsyncEnumerable。只有实现IDbAsyncEnumerable的源才能用于Entity Framework异步操作。

据此:Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations我需要将EF添加到我的UnitTest项目中。 但是错误仍然存​​在。

ListAsync 方法如下:

public async Task<List<Sortation>> ListAsync(string categoryId, params string[] includes) => 
    await _sortationService.List(includes).Where(m => m.CategoryId.Equals(categoryId)).ToListAsync();

有人知道我如何阻止此错误的发生?

1 个答案:

答案 0 :(得分:0)

不知道问题是否仍然存在,但仍然存在。我同意Mark的评论,但是以下示例对我有用。我为提到的类添加了一些合理的存根实现,因为这里没有问题。我的假设可能是错误的:

[Test]
public async Task ShouldHaveOrderOfZero()
{
    // Assemble
    const string categoryId = "cameras";
    var services = SortationContext.GivenServices();
    var sortationProvider = services.WhenGetSortationProvider();
    var sortations = new List<Sortation>();
    var sortation = new Sortation { CategoryId = categoryId };

    // the key moq configuration here
    services.MockSortationService.Setup(x => x.ListAsync(It.IsAny<string>())).Returns(Task.FromResult(sortations));

    // Act
    await sortationProvider.SaveAsync(sortation);

    // Assert
    sortation.Order.Should().Be(0);
}

public class SortationProvider
{
    private SortationService _sortationService;

    public SortationProvider()
    {
        _sortationService = new SortationService();
    }

    public async Task<Sortation> SaveAsync(Sortation sortation)
    {
        if (sortation.Id == 0)
        {
            var sortations = await ListAsync(sortation.CategoryId);
            sortation.Order = sortations.Count;
            _sortationService.Create(sortation);
        }
        else
        {
            _sortationService.Update(sortation);
        }

        await _sortationService.SaveChangesAsync();

        return sortation;
    }

    // should be virtual
    public virtual async Task<List<Sortation>> ListAsync(string categoryId, params string[] includes) =>
        await _sortationService.List(includes).Where(m => m.CategoryId.Equals(categoryId)).ToListAsync();

}

public class SortationContext
{
    public static Services GivenServices()
    {
        return new Services();
    }
}

public class Services
{
    public Services()
    {
        MockSortationService = new Mock<SortationProvider>();
    }

    public SortationProvider WhenGetSortationProvider()
    {
        return MockSortationService.Object;
    }

    public Mock<SortationProvider> MockSortationService { get; set; }
}

internal class SortationService
{
    public void Create(Sortation sortation)
    {

    }

    public void Update(Sortation sortation)
    {

    }

    public Task SaveChangesAsync()
    {
        return Task.CompletedTask;
    }

    public DbSet<Sortation> List(string[] includes)
    {
        throw new NotImplementedException();
    }
}

public class Sortation
{
    public string CategoryId { get; set; }
    public int Id { get; set; }
    public int Order { get; set; }
}

主要更改是包含Setup方法的行。我也将ListAsync方法设为虚拟。主要假设是List(string[] includes)方法返回DbSet<Sortation>。希望对您有所帮助。