Asp.Net核心unit testing异步控制器

我有这个测试:

[Fact] public async void Can_Paginate() { //fake data var product1 = new Product { ProductId = 1, ProductName = "P1" }; var product2 = new Product { ProductId = 2, ProductName = "Product 2" }; var product3 = new Product { ProductId = 3, ProductName = "Product 3" }; var product4 = new Product { ProductId = 4, ProductName = "Product 4" }; var product5 = new Product { ProductId = 5, ProductName = "Product 5" }; var data = new List { product1, product2, product3, product4, product5 }.ToAsyncEnumerable(); var category1 = new Category { CategoryId = 1 }; var prodCategoryData = new List { new ProductCategory { Product =product1,Category = category1}, new ProductCategory { Product =product2,Category = category1}, new ProductCategory { Product =product3,Category = category1}, new ProductCategory { Product =product4,Category = category1}, new ProductCategory { Product =product5,Category = category1} }.ToAsyncEnumerable(); var dbSetMock = new Mock<DbSet>(); //dbSetMock.As<IQueryable>().Setup(m => m.Provider).Returns(data.Provider); //dbSetMock.As<IQueryable>().Setup(m => m.Expression).Returns(data.Expression); //dbSetMock.As<IQueryable>().Setup(m => m.ElementType).Returns(data.ElementType); //dbSetMock.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); var pcDbSetMock = new Mock<DbSet>(); // pcDbSetMock.As<IQueryable>().Setup(m => m.Provider).Returns(prodCategoryData.Provider); //pcDbSetMock.As<IQueryable>().Setup(m => m.Expression).Returns(prodCategoryData.Expression); //pcDbSetMock.As<IQueryable>().Setup(m => m.ElementType).Returns(prodCategoryData.ElementType); //pcDbSetMock.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(prodCategoryData.GetEnumerator()); Mock customDbContextMock = new Mock(); customDbContextMock.Setup(x => x.Products).Returns(dbSetMock.Object); customDbContextMock.Setup(x => x.ProductCategories).Returns(pcDbSetMock.Object); var loggerMock = new Mock<ILogger>(); var envMock = new Mock(); var httpContext = new Mock().Object; var actionDescriptor = new Mock().Object; var modelState = new ModelStateDictionary(); var actionContext = new ActionContext(httpContext, new Mock().Object, actionDescriptor, modelState); ProductsController controller = new ProductsController(customDbContextMock.Object, loggerMock.Object, envMock.Object); controller.pageSize = 3; controller.ControllerContext = new ControllerContext(actionContext); var result = await controller.List(1, 2); 

我的控制器逻辑:

 public async Task List(int Id, int page = 1) { if (Id == 0) { ViewBag.CategoryName = "Wszystkie produkty"; return View(await _context.ProductCategories.Include(c => c.Product).ToListAsync()); } return View(await _context.ProductCategories .Include(p => p.Product) .Where(pt => pt.CategoryId == Id) .OrderBy(p=>p.ProductId) .Skip((page-1)*pageSize) .ToListAsync()); } 

我的问题是我不能通过使用prodCategoryData和数据列表作为IAsyncEnumerable来模拟IAsyncEnumerable

当我将它们转换为IQueryable我得到了这个错误:

附加信息:源IQueryable未实现IAsyncEnumerable。 只有实现IAsyncEnumerable的源才能用于Entity Framework。

使用此答案中的测试类:

如何使用Entity Framework Core模拟异步存储库

导出了以下通用扩展方法

 public static Mock> ToAsyncDbSetMock(this IEnumerable source) where T : class { var data = source.AsQueryable(); var mockSet = new Mock>(); mockSet.As>() .Setup(m => m.GetEnumerator()) .Returns(new TestAsyncEnumerator(data.GetEnumerator())); mockSet.As>() .Setup(m => m.Provider) .Returns(new TestAsyncQueryProvider(data.Provider)); mockSet.As>().Setup(m => m.Expression).Returns(data.Expression); mockSet.As>().Setup(m => m.ElementType).Returns(data.ElementType); mockSet.As>().Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator()); return mockSet; } 

使用上述扩展方法,可以对测试进行重构

 [Fact] public async Task Can_Paginate() { //Arrange var products = GetFakeProducts().ToAsyncDbSetMock(); var productCategories = GetFakeProductCategories().ToAsyncDbSetMock(); var customDbContextMock = new Mock(); customDbContextMock.Setup(x => x.Products).Returns(products.Object); customDbContextMock.Setup(x => x.ProductCategories).Returns(productCategories.Object); //...other code removed for brevity var controller = new ProductsController(customDbContextMock.Object, loggerMock.Object, envMock.Object); controller.pageSize = 3; controller.ControllerContext = new ControllerContext(actionContext); //Act var result = await controller.List(1, 2); //Assert //...other code removed for brevity }