尝试对通用存储库进行C#单元测试时,出现一个奇怪的错误“无法从IStudentContext转换为TestStudentContext”。看来我需要在接口中重新实现.Set(),对吗?为了简洁起见,省略了一些代码,但这是基本设置。原谅大块代码,我将在底部添加一些其他上下文!IStudentContext.cs
public interface IStudentContext : IDisposable
{
Database Database { get; }
// Irrelevant tables omitted
DbSet<Class> Classes { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync();
}
StudentContext.cs
public class StudentContext : DbContext, IStudentContext
{
public StudentContext() : base("name=StudentContext") {}
// Irrelevant tables omitted
public virtual DbSet<Class> Classes { get; set; }
}
TestStudentContext.cs
public class TestStudentContext : DbContext, IStudentContext
{
public TestStudentContext(DbConnection connection) : base(connection, contextOwnsConnection: true) {}
// Irrelevant tables omitted
public virtual DbSet<Class> Classes { get; set; }
}
EntityFrameworkReadOnlyRepository.cs
public class EntityFrameworkReadOnlyRepository<TContext> : IGenericReadOnlyRepository where TContext : DbContext, IStudentContext
{
protected readonly TContext Context;
public EntityFrameworkReadOnlyRepository(TContext context)
{
Context = context;
}
// Irrelevant generic repo methods omitted
public IEnumerable<TEntity> Get<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string include = null, int? skip = null, int? take = null)
{
return GetQueryable(filter, orderBy, include, skip, take).ToList();
}
protected virtual IQueryable<TEntity> GetQueryable<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string include = null, int? skip = null, int? take = null)
{
include = include ?? string.Empty;
IQueryable<TEntity> query = Context.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
query = include.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, property) => current.Include(property));
if (orderBy != null)
query = orderBy(query);
if (skip.HasValue)
query = query.Skip(skip.Value);
if (take.HasValue)
query = query.Take(take.Value);
return query;
}
}
StudentRepositoryTests.cs
public class StudentRepositoryTests
{
private IStudentContext Context { get; set; }
[TestInitialize]
public void Initialize()
{
Context = new TestStudentContext(Effort.DbConnectionFactory.CreateTransient());
}
[TestMethod]
public void GetClasses_OrdersCorrectly()
{
// Calls to Context.Classes.Add() to set up DB omitted
Context.SaveChanges();
var repository = new EntityFrameworkReadOnlyRepository<TestStudentContext>(Context);
var results = repository.Get<Classes>().ToArray();
// Assertions omitted
}
}
如前所述,我在测试类的
Context
行中的var repository
上出现错误。错误状态为Argument 1: cannot convert from 'IStudentContext' to 'TestStudentContext'
。如果我将该行更改为var repository = new EntityFrameworkReadOnlyRepository<IStudentContext>(Context);
,则会出现错误The type 'IStudentContext' cannot be used as type parameter 'TContext' in the generic type or method 'EntityFrameworkReadOnlyRepository<TContext>'. There is no implicit reference conversion from 'IStudentContext' to 'System.Data.Entity.DbContext'.
看起来如果我为
IStudentContext
中的所有数据库表实现DbSet可能会解决此问题,但感觉就像我正在重新实现大量代码只是为了能够测试某些东西,因此我认为将会有一个更简单的方法。 最佳答案
在
var repository = new EntityFrameworkReadOnlyRepository<TestStudentContext>(Context);
Context
的类型为IStudentContext
。因此,您不能将该值传递给期望TestStudentContext
的ctor。一个简单的解决方法是使
private IStudentContext Context { get; set; }
的类型为TestStudentContext
。或者,如果要保留它IStudentContext
然后进行转换,或者找到另一种传递该值的方法而又不向上转换为IStudentContext
,则在此过程中首先丢失类型信息。看来我需要在接口中重新实现.Set(),对吗?
那没有必要。编译器消息指出了我解决的问题。
在您的存储库中,您选择了让呼叫者指定位置,排序依据等。这对我而言似乎不是一种有用的方法。最好有一个
QueryTable<T>()
方法,并使调用方构造查询。您可以创建一个辅助函数来构建这样的查询(我认为这是没有用的),但是不必使存储库负责构建LINQ查询。我还粗略地注意到
TContext
参数似乎不是必需的。您可以直接使用DbContext
并进行简化。关于c# - 测试通用接口(interface)时出现奇怪的接口(interface)/TContext错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45841566/