尝试对通用存储库进行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/

10-09 18:49