等待和where子句

时间:2018-08-01 11:17:30

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

我的课堂上有以下方法代码:

public async Task<int> TestMethodAsync()
{
    var code = await Context.DataCodes
            .Include(x => x.Text)
            .Where(x => x.Code == "HI")
            .ToListAsync();
    return 1;
}

public int TestMethod()
{
    var code = Context.DataCodes
            .Include(x => x.Text)
            .Where(x => x.Code == "HI")
            .ToList();
    return 1;
}

以及以下单元测试类:

namespace ControllerUnitTests.ServiceTests
{
    [TestFixture]
    class UsersServiceTests
    {
        private IDataContext<ClearviewLocalContext> _context;
        private Mock<ClearviewLocalContext> _dbContext;

        private Mock<IDescriptionService> _descriptionService;
        private Mock<IFilterService> _filterService;
        private Mock<IApplicationUserService> _userService;
        private Mock<IGroupingService> _groupingService;
        private Mock<ISelectionListsService> _selectionService;
        private Mock<IActionLogService> _actionLogService;

        private IAuditService _auditService;

        /// <summary>
        /// Constructor
        /// </summary>
        [SetUp]
        public void setup()
        {
            _dbContext = new Mock<ClearviewLocalContext>();
            _descriptionService = new Mock<IDescriptionService>();
            _filterService = new Mock<IFilterService>();
            _userService = new Mock<IApplicationUserService>();
            _groupingService = new Mock<IGroupingService>();
            _selectionService = new Mock<ISelectionListsService>();
            _actionLogService = new Mock<IActionLogService>();

            var dataCodesLists = new List<t_Data_DataCodes>();
            dataCodesLists.Add(new t_Data_DataCodes { UNID = 1, Code = "HI" });
            var dbDataCodesLists = MockDbSet.GetQueryableMockDbSet(dataCodesLists);

            _dbContext.Setup(x => x.DataCodes).Returns(dbDataCodesLists.Object);

            _context = new DataContext<ClearviewLocalContext, ClearviewLocalContext>(_dbContext.Object);

            _auditService = new AuditService(_context, _descriptionService.Object, _filterService.Object, _userService.Object, _groupingService.Object, _selectionService.Object, _actionLogService.Object);        
        }

        [Test]
        public async Task TestAsync()
        {
            var res = await _auditService.TestMethodAsync();
            Assert.That(res == 1);
        }

        [Test]
        public async Task Test()
        {
            var res = _auditService.TestMethod();
            Assert.That(res == 1);
        }
    }
}

使用:

public static Mock<DbSet<T>> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
{
    var queryable = sourceList.AsQueryable();

    var dbSet = new Mock<DbSet<T>>();

    dbSet.As<IDbAsyncEnumerable<T>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<T>(queryable.GetEnumerator()));
    dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<T>(queryable.Provider));
    dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
    dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
    dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
    dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

    dbSet.Setup(x => x.Include(It.IsAny<string>())).Returns(dbSet.Object);
    dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));

    return dbSet;
}

最后:

namespace ControllerUnitTests.Helpers
{
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider 
    { 
        private readonly IQueryProvider _inner; 

        internal TestDbAsyncQueryProvider(IQueryProvider inner) 
        { 
            _inner = inner; 
        } 

        public IQueryable CreateQuery(Expression expression) 
        { 
            return new TestDbAsyncEnumerable<TEntity>(expression); 
        } 

        public IQueryable<TElement> CreateQuery<TElement>(Expression expression) 
        { 
            return new TestDbAsyncEnumerable<TElement>(expression); 
        } 

        public object Execute(Expression expression) 
        { 
            return _inner.Execute(expression); 
        } 

        public TResult Execute<TResult>(Expression expression) 
        { 
            return _inner.Execute<TResult>(expression); 
        } 

        public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) 
        { 
            return Task.FromResult(Execute(expression)); 
        } 

        public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) 
        { 
            return Task.FromResult(Execute<TResult>(expression)); 
        } 
    } 

    internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T> 
    { 
        public TestDbAsyncEnumerable(IEnumerable<T> enumerable) 
            : base(enumerable) 
        { } 

        public TestDbAsyncEnumerable(Expression expression) 
            : base(expression) 
        { } 

        public IDbAsyncEnumerator<T> GetAsyncEnumerator() 
        { 
            return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); 
        } 

        IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() 
        { 
            return GetAsyncEnumerator(); 
        } 

        IQueryProvider IQueryable.Provider 
        { 
            get { return new TestDbAsyncQueryProvider<T>(this); } 
        } 
    } 

    internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> 
    { 
        private readonly IEnumerator<T> _inner; 

        public TestDbAsyncEnumerator(IEnumerator<T> inner) 
        { 
            _inner = inner; 
        } 

        public void Dispose() 
        { 
            _inner.Dispose(); 
        } 

        public Task<bool> MoveNextAsync(CancellationToken cancellationToken) 
        { 
            return Task.FromResult(_inner.MoveNext()); 
        } 

        public T Current 
        { 
            get { return _inner.Current; } 
        } 

        object IDbAsyncEnumerator.Current 
        { 
            get { return Current; } 
        } 
    } 
}

TestDbAsyncQueryProvider是该站点https://msdn.microsoft.com/en-gb/data/dn314429的复制和粘贴

最后我的单元测试:

[Test]
public async Task TestAsync()
{
    var res = await _auditService.TestMethodAsync();
    Assert.That(res == 1);
}

[Test]
public async Task Test()
{
    var res = _auditService.TestMethod();
    Assert.That(res == 1);
}

问题是TestAsync抛出以下异常:

The source IQueryable doesn't implement IDbAsyncEnumerable<ClearviewLocal_Core_DAL.TableModels.t_Data_DataCodes>. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see

但是据我所知,我已经在我的TestDbAsyncQueryProvider类中实现了该功能-正如我上面所说的,这是一个复制和粘贴工作-我真的不知道它在做什么。

进一步说明-Test()有效,如果我从Where中删除TestAsync子句也有效。

因此,问题似乎来自WhereAsync的结合,但我不知道如何解决此问题-我们将不胜感激。

0 个答案:

没有答案