如何写这个EF模拟设置代码为可重复使用通用的样板?

编程入门 行业动态 更新时间:2024-10-23 21:31:01
本文介绍了如何写这个EF模拟设置代码为可重复使用通用的样板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我用的起订量,EF 6和的xUnit。我发现自己一遍又一遍地编写这些代码,也许以为我可以把它变成一个通用的方法,但遇到一些麻烦。

I am using moq, ef 6 and xunit. I find myself writing this code over and over and thought maybe I could make it into a generic method but having some trouble.

public static void CreateSalesMock(List<Sale> sales, Mock<DatabaseContext> dbContextMock) { var data = sales.AsQueryable(); var mockSet = new Mock<DbSet<Sale>>(); mockSet.As<IQueryable<Sale>>() .Setup(x => x.Provider) .Returns(data.Provider); mockSet.As<IQueryable<Sale>>() .Setup(x => x.Expression) .Returns(data.Expression); mockSet.As<IQueryable<Sale>>() .Setup(x => x.ElementType) .Returns(data.ElementType); mockSet.As<IQueryable<Sale>>() .Setup(x => x.GetEnumerator()) .Returns(data.GetEnumerator()); dbContextMock.Setup(x => x.Sales).Returns(mockSet.Object); }

现在我有很多其他表在我的数据库,所以如果我可以写一个方法这将需要该数据的列表,并设定,让我可以模拟查询通过这将是巨大的。

Now I have many other tables in my database so if I could write one method that would take in a list of that data and set it up so I can mock query through it would be great.

public static void CreateMockSet<T, TA, TB>(T dataList, TA model, Func<TB> lambda, Mock<DatabaseContext> dbContextMock) where T : List<T> where TA: Mock<DbSet<TA>> { var data = dataList.AsQueryable(); model.As<IQueryable<T>>() .Setup(x => x.Provider) .Returns(data.Provider); model.As<IQueryable<T>>() .Setup(x => x.Expression) .Returns(data.Expression); model.As<IQueryable<T>>() .Setup(x => x.ElementType) .Returns(data.ElementType); model.As<IQueryable<T>>() .Setup(x => x.GetEnumerator()) .Returns(data.GetEnumerator()); dbContextMock.Setup(x => lambda); }

到目前为止,我有这一点,但我不知道是否会工作或没有。我被困传入拉姆达的一部分( X => x.Sales 为例),所以我甚至无法对其进行测试。

So far I have that but I am not sure if that will work or not. I am stuck passing in the "lambda" part(x => x.Sales for example) so I can't even test it.

推荐答案

蒂姆·拉尔森已经提供了对的他的博客:

Tim Larson already offered a great solution for this boilerplate code in his blog:

public static class DbSetMocking { private static Mock<DbSet<T>> CreateMockSet<T>(IQueryable<T> data) where T : class { var queryableData = data.AsQueryable(); var mockSet = new Mock<DbSet<T>>(); mockSet.As<IQueryable<T>>().Setup(m => m.Provider) .Returns(queryableData.Provider); mockSet.As<IQueryable<T>>().Setup(m => m.Expression) .Returns(queryableData.Expression); mockSet.As<IQueryable<T>>().Setup(m => m.ElementType) .Returns(queryableData.ElementType); mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()) .Returns(queryableData.GetEnumerator()); return mockSet; } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, TEntity[] entities) where TEntity : class where TContext : DbContext { Mock<DbSet<TEntity>> mockSet; return ReturnsDbSet(setup, entities, out mockSet); } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, IQueryable<TEntity> entities) where TEntity : class where TContext : DbContext { Mock<DbSet<TEntity>> mockSet; return ReturnsDbSet(setup, entities, out mockSet); } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, IEnumerable<TEntity> entities) where TEntity : class where TContext : DbContext { Mock<DbSet<TEntity>> mockSet; return ReturnsDbSet(setup, entities, out mockSet); } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, TEntity[] entities, out Mock<DbSet<TEntity>> mockSet) where TEntity : class where TContext : DbContext { mockSet = CreateMockSet(entities.AsQueryable()); return setup.Returns(mockSet.Object); } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, IQueryable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet) where TEntity : class where TContext : DbContext { mockSet = CreateMockSet(entities); return setup.Returns(mockSet.Object); } public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>( this IReturns<TContext, DbSet<TEntity>> setup, IEnumerable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet) where TEntity : class where TContext : DbContext { mockSet = CreateMockSet(entities.AsQueryable()); return setup.Returns(mockSet.Object); } }

然后在UT你使用它如下所示:

Then in the UT you use it as the following:

var context = new Mock<DatabaseContext>(); context.setup(x => x.Sales).ReturnsDbSet(new List<Sale>(){put here the items..});

修改

我更新的代码。现在有3个重载它允许在 DbSet<验证; T> 属性:

I updated the code. Now there are 3 more overloads which allows verification on DbSet<T> property:

[TestMethod] public void TestMethod1() { var sales = new List<Sale> { new Sale() {id = 1}, new Sale() {id = 6}, new Sale() {id = 5}, new Sale() {id = 4}, new Sale() {id = 3}, new Sale() {id = 2} }; var fakeContest = new Mock<SalesContext>(); Mock<DbSet<Sale>> fakeSet; fakeContest.Setup(context => context.Sales).ReturnsDbSet(sales, out fakeSet); var itemsToRemove = sales.Where(sale => sale.id%2 == 0); fakeContest.Object.Sales.RemoveRange(itemsToRemove); fakeSet.Verify(set => set.RemoveRange(itemsToRemove)); }

更多推荐

如何写这个EF模拟设置代码为可重复使用通用的样板?

本文发布于:2023-11-16 22:03:50,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1607649.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:样板   重复使用   如何写   代码   EF

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!