2016-12-06 176 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*)));