【问题标题】:MSTest v2 and The source IQueryable doesn't implement IAsyncEnumerable with Entity Framework CoreMSTest v2 和源 IQueryable 未使用 Entity Framework Core 实现 IAsyncEnumerable
【发布时间】:2020-04-20 20:54:54
【问题描述】:

我正在尝试为 DAL 库(EF 核心)创建单元测试(MSTest v2)

数据服务

    public IQueryable<BalanceDTO> GetCollection()
    {
        var entities = dbContext.Balance;
        var dtos = mapper.Map<ICollection<BalanceDTO>>(entities).ToList();
        dtos.ForEach(_d =>
        {
            _d.MonthSort = _d.Date.Month;
            _d.MonthName = (new DateTimeFormatInfo()).GetMonthName(_d.MonthSort);
        });
        return dtos.AsQueryable();
    }

    public async Task<IList<BalanceDTO>> GetBalancesByYear(int year)
    {
        return await GetCollection().Where(_d => _d.Date.Year == year).OrderBy(_d => _d.MonthSort).ToListAsync();
    }

测试

    [TestMethod()]
    [DataTestMethod]
    [DataRow(2020, 2019)]
    public void GetBalancesByYearTest(int found, int notfound)
    {
        var _configuration = new ConfigurationBuilder()
            .SetBasePath(AssemblyProperties.AssemblyDirectory)
            .AddJsonFile("appsettings.json")
            .Build();
        var optionsBuilder = new DbContextOptionsBuilder<AccountManagerContext>();
        optionsBuilder.UseSqlServer(_configuration.GetConnectionString("AccountManagerLocalDB"));

        var balanceDataService = new BalanceDataService(optionsBuilder);
        var elementsFound = balanceDataService.GetBalancesByYear(found);
        var elementsNotFound = balanceDataService.GetBalancesByYear(notfound);

        Assert.IsNotNull(balanceDataService);
        Assert.IsTrue(elementsFound.Result.Count > 0);
        Assert.IsTrue(elementsNotFound.Result.Count == 0);
    }

但我收到此错误:

InvalidOperationException: The source IQueryable doesn't implement IAsyncEnumerable<AccountManager.DAL.DTO.BalanceDTO>. 
Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.

我找到了几个链接,但不知道如何解决这个问题。

ToArrayAsync() throws "The source IQueryable doesn't implement IAsyncEnumerable"

How to overcome the IQueryable doesn't implement IAsyncQueryProvider while Mocking the FromSql() method?

知道如何为我的 DataService 方法创建测试吗?

【问题讨论】:

    标签: c# unit-testing async-await entity-framework-core mstest


    【解决方案1】:

    Entity Framework 与DbSets 一起工作,这不仅仅是可查询的。

    您可以use the In-Memory provider for your tests,或mock the Dbsets

    【讨论】:

    • 谢谢,这不是 xUnit 的吗?
    • 我明白了。但这仍然不能解决我在使用这些方法时面临的问题。 GetBalancesByYear 抛出相同的异常。我不能直接使用使用 DbSet,因为我需要使实体适应相应的DTO
    • GetBalancesByYear 是否在您的单元测试之外工作? AsQueryable 在测试之外通常是代码异味。无论你认为它在做什么,
    • 到目前为止...是的,或者至少我是这么认为的。当我调用 GetColletion() 方法时,我在 SQL 分析器 SELECT [b].[BalanceID], [b].[Date], [b].[DateClosed], [b].[FinalAmount], [b].[InitialAmount], [b].[PercentVariation], [b].[Variation] FROM [Balance] AS [b] 中看到了将 DbSet 与 AutoMapper 一起使用的解决方案,您会推荐什么?
    • 我已经有好几年没有使用 AutoMapper,但我记得它在重写查询方面做得很好。检查他们的文档。
    【解决方案2】:

    我最终得到了这个解决方案。 如果有人发现错误或需要改进的地方,我非常感谢任何建议。

        public IQueryable<BalanceDTO> GetCollection()
        {
            var entities = dbContext.Balance;
            var dtos = mapper.Map<ICollection<BalanceDTO>>(entities);
            foreach(var _d in dtos)
            {
                _d.MonthSort = _d.Date.Month;
                _d.MonthName = (new DateTimeFormatInfo()).GetMonthName(_d.MonthSort);
            };
            return dtos.AsQueryable();
        }
    
        public async Task<IList<BalanceDTO>> GetBalancesByYear(int year)
        {
            var entities = dbContext.Balance.Where(_d => _d.Date.Year == year).OrderBy(_d => _d.Date);
            var balanceDTOs = Task<IList<BalanceDTO>>.Factory.StartNew(() =>
            {
                var dtos = mapper.Map<IList<BalanceDTO>>(entities);
    
                foreach (var _d in dtos)
                {
                    _d.MonthSort = _d.Date.Month;
                    _d.MonthName = (new DateTimeFormatInfo()).GetMonthName(_d.MonthSort);
                };
                return dtos;
            });
    
            return await balanceDTOs;
        }
    

    我已经修改了GetBalancesByYear,因此它不使用GetCollection,因为如果它必须收集完整的元素集合并将它们转换为 DTO,然后过滤不需要的元素,它就不会高效.

    当我的 DAL 需要返回 DTO 而不仅仅是实体时,我对谁为我的 DAL 正确创建异步方法感到很困惑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-02
      • 2021-01-02
      • 1970-01-01
      • 2017-04-07
      • 1970-01-01
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多