2014-01-10 66 views
0

我正在創建一個模擬IDbSet,以允許對實體框架類進行單元測試等等。如何檢測更改IDbSet

但是,我真的無法檢測到變化,甚至根本沒法弄清楚如何去做。下面是我的課那麼遠,

public interface IReportContext 
{ 
    IDbSet<Report> Reports {get;} 
    public int SaveChanges(); 
} 

public class MockReportContext : IReportContext 
{ 
    IDbSet<Report> Reports {get;} 

    public int SaveChanges() 
    { 
     //Need to detect changes here??? 
    } 

    public MockReportContext() 
    { 
     Reports = new MockDbSet<Report>(); 
    } 
} 

public class MockDbSet<T> : IDbSet<T> 
{ 
    readonly ObservableCollection<T> _data; 
    readonly IQueryable _query; 

    public FakeDbSet() 
    { 
     _data = new ObservableCollection<T>(); 
     _query = _data.AsQueryable(); 
    } 

    public FakeDbSet(ObservableCollection<T> data) 
    { 
     _data = data; 
     _query = _data.AsQueryable(); 
    } 

    public virtual T Find(params object[] keyValues) 
    { 
     throw new NotImplementedException(); 
    } 

    public T Add(T item) 
    { 
     _data.Add(item); 
     return item; 
    } 

    public T Remove(T item) 
    { 
     _data.Remove(item); 
     return item; 
    } 

    public T Attach(T item) 
    { 
     _data.Add(item); 
     return item; 
    } 

    public T Detach(T item) 
    { 
     _data.Remove(item); 
     return item; 
    } 

    public T Create() 
    { 
     return Activator.CreateInstance<T>(); 
    } 

    public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T 
    { 
     return Activator.CreateInstance<TDerivedEntity>(); 
    } 

    public ObservableCollection<T> Local 
    { 
     get { return _data; } 
    } 

    Type IQueryable.ElementType 
    { 
     get { return _query.ElementType; } 
    } 

    System.Linq.Expressions.Expression IQueryable.Expression 
    { 
     get { return _query.Expression; } 
    } 

    IQueryProvider IQueryable.Provider 
    { 
     get { return _query.Provider; } 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return _data.GetEnumerator(); 
    } 

    IEnumerator<T> IEnumerable<T>.GetEnumerator() 
    { 
     return _data.GetEnumerator(); 
    } 
} 

這正常添加,刪除和檢索實體。然而,當我嘗試以下方法:

IReportContext context = new MockReportContext(); 
context.Reports.Add(new Report()); //Works 
Report report = context.Reports.First(); //Works 
report.Message = "Hello World!"; 
context.SaveChanges(); //Does nothing 

它是如何在MockReportContext可以知道它返回的報表對象發生了變化?我知道使用實體框架這樣做,所以它必須是可能的,但我沒有得到一個線索如何...

回答

0

我認爲你主要在那裏,但我建議使用嘲笑框架,如Moq(我的個人偏好)或Rhino Mocks來模擬你的單元測試的IReportContext,而不是去創建像MockReportContext這樣的Fake類的麻煩。 (好吧,學習一個嘲諷的框架確實會帶來一些麻煩,但是它會在很短的時間內節省很多假類的苦差事。)

我假設你正在單元測試取決於IReportContext的代碼,所以你不需要在SaveChanges()裏面做任何事情,你只需要聲明你的代碼在內部應該叫做SaveChanges()

Here's a good overview使用Moq與實體框架的派生DbContext/DbSet類。

在上面的鏈接的概述,如果在最後的單元測試是測試在內部調用SaveChanges()的方法,可以附加驗證SaveChanges()確實是由你的方法用線稱爲:

dc.Verify(db => db.SaveChanges()); 

你也可以通過在SaveChanges()類中將side屬性設置爲True並在單元測試結束時對其進行檢查來對MockReportContext類執行此操作,但模擬框架更加靈活,並且不需要爲單元測試編寫其他類。

如果你想避免使用模擬框架,那麼這裏的how to do it with fakes