模拟 Entity Framework 存储库模式
Mocking Entity Framework repository pattern
我有一个接口定义为:
public interface IRepository<TEntity> where TEntity : BaseEntity
{
...
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
...
}
我的实现是:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
{
internal MyContext context;
internal DbSet<TEntity> dbSet;
public Repository(MyContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
}
最后是调用此代码的我的代码:
Repository.Get(r =>
r.SourceOrganisationId == id,
null, // No ordering
"DestinationOrganisation") // Include the company
.Select(d => d.DestinationOrganisation).OrderBy(c => c.Name);
我想对我的查询进行单元测试,以确保我有正确的 where 子句,并且我在结果中包含了一个额外的实体。
我一直在研究如何使用 Moq 模拟 DbContext 和 DbSet,但看不到如何仍然具有包含的 EF 功能。我发现的大多数示例都模拟了一个简单的 GetById。基本上我不想模拟 EF,只是让它从内存中读取而不是从 Db 中读取。
有什么想法吗?
谢谢
在进一步研究之后,我意识到我想做的事是不可能的。
我想要的是用内存存储模拟数据库,然后测试我的查询是否有效,包括 Include
方法(例如,有一些包含相关实体的测试和一些不包含相关实体的测试) .我不想模拟 Include
我实际上希望它按照我的内存列表执行。这是不可能的,因为从以下 here:
One example of such a difference is loading related data. If you create a series of Blogs that each have related Posts, then when using in-memory data the related Posts will always be loaded for each Blog. However, when running against a database the data will only be loaded if you use the Include method.
For this reason, it is recommended to always include some level of
end-to-end testing (in addition to your unit tests) to ensure your
application works correctly against a database.
有一个名为 Effort 的工具非常适合 Entity Framework 单元测试。可能值得一看,看看它是否符合您的要求?
来自他们的主页:
It is basically an ADO.NET provider that executes all the data operations on a lightweight in-process main memory database instead of a traditional external database
我有一个接口定义为:
public interface IRepository<TEntity> where TEntity : BaseEntity
{
...
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
...
}
我的实现是:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
{
internal MyContext context;
internal DbSet<TEntity> dbSet;
public Repository(MyContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
}
最后是调用此代码的我的代码:
Repository.Get(r =>
r.SourceOrganisationId == id,
null, // No ordering
"DestinationOrganisation") // Include the company
.Select(d => d.DestinationOrganisation).OrderBy(c => c.Name);
我想对我的查询进行单元测试,以确保我有正确的 where 子句,并且我在结果中包含了一个额外的实体。
我一直在研究如何使用 Moq 模拟 DbContext 和 DbSet,但看不到如何仍然具有包含的 EF 功能。我发现的大多数示例都模拟了一个简单的 GetById。基本上我不想模拟 EF,只是让它从内存中读取而不是从 Db 中读取。
有什么想法吗?
谢谢
在进一步研究之后,我意识到我想做的事是不可能的。
我想要的是用内存存储模拟数据库,然后测试我的查询是否有效,包括 Include
方法(例如,有一些包含相关实体的测试和一些不包含相关实体的测试) .我不想模拟 Include
我实际上希望它按照我的内存列表执行。这是不可能的,因为从以下 here:
One example of such a difference is loading related data. If you create a series of Blogs that each have related Posts, then when using in-memory data the related Posts will always be loaded for each Blog. However, when running against a database the data will only be loaded if you use the Include method.
For this reason, it is recommended to always include some level of end-to-end testing (in addition to your unit tests) to ensure your application works correctly against a database.
有一个名为 Effort 的工具非常适合 Entity Framework 单元测试。可能值得一看,看看它是否符合您的要求?
来自他们的主页:
It is basically an ADO.NET provider that executes all the data operations on a lightweight in-process main memory database instead of a traditional external database