2014-01-10 69 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