2016-12-06 178 views
0

我有一种情况,我通过包装使用上下文。包装器用于服务层。问题是如何在这种情况下模拟上下文?如何通过包装模拟上下文

语境

public class DbContext : System.Data.Entity.DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     ... 

     base.OnModelCreating(modelBuilder); 
    } 

    public DbSet<Report> Reports { get; set; } 
} 

包装

public interface IDbContextWrapper<out TContext> where TContext : System.Data.Entity.DbContext, new() 
{ 
    T Call<T>(Func<TContext, T> func); 

    void Call(Action<TContext> action); 
} 

包装实施

public class DbContextWrapper<TContext> : IDbContextWrapper<TContext> where TContext : System.Data.Entity.DbContext, new() 
{ 

    public virtual TContext BuildContext(bool enableChangeTracking = true, bool enableLazyLoading = false, bool enableProxyCreation = false) 
    { 
     var result = new TContext(); 
     result.Configuration.AutoDetectChangesEnabled = enableChangeTracking; 
     result.Configuration.LazyLoadingEnabled = enableLazyLoading; 
     result.Configuration.ProxyCreationEnabled = enableProxyCreation; 
     return result; 
    } 

    public virtual T Call<T>(Func<TContext, T> func) 
    { 
     using (var context = BuildContext()) 
     { 
      return func(context); 
     } 
    } 

    public virtual void Call(Action<TContext> action) 
    { 
     using (var context = BuildContext()) 
     { 
      action(context); 
     } 
    } 
} 

,服务和它的方法,我需要进行单元测试与嘲笑

public class ReportService : IReportService 
{ 
    private readonly IDbContextWrapper<DbContext> _contextWrapper; 

    public ReportService(IDbContextWrapper<DbContext> contextWrapper) 
    { 
     _contextWrapper = contextWrapper; 
    } 


    public Report GetPreviousReport(int currentReportId, int lineId) 
    { 
     return _contextWrapper.Call(
      context => context.Reports 
       .Where(item => item.Id < currentReportId && item.LineId == lineId) 
       .OrderBy(item => item.Id) 
       .First()); 
    } 

    public Report GetNextReport(int currentReportId, int lineId) 
    { 
     return _contextWrapper.Call(
      context => context.Reports 
       .Where(item => item.Id > currentReportId && item.LineId == lineId) 
       .OrderBy(item => item.Id) 
       .First()); 
    } 
} 

回答

1

在您的测试中,您可以创建StubTContext并初始化报告以返回测试数据。然后使用IDbContextWrapper将您的系统初始化为ReportService。

这个准备后,使用起订量嘲笑IDbContextWrapper,像这样:

Mock<IDbContextWrapper<StubTContext>> mock = new Mock<IDbContextWrapper<StubTContext>>(); 

mock.Setup(m => m.Call(It.IsAny<Action<StubTContext>>())).Callback<Action<StubTContext>>(a => a.Invoke(new StubTContext())); 

你也可以在样机通过测试数据为它实施StubTContext提供通过构造函数的测试数据,然后。事情是这样的:

public StubTContext : DbContext 
{ 
    public StubTContex(DbSet<Report> reports) 
    { 
     Reports = reports; 
    } 
} 

,然后在模拟

mock.Setup(m => m.Call(It.IsAny<Action<StubTContex>>())).Callback<Action<StubTContex>>(a => a.Invoke(new StubTContex(*YOUR REPORTS*)));