2014-01-10 5 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 мог знать, что объект отчета он вернулся изменился ?? Я знаю, что использование сущности framework делает это так, чтобы это было возможно, но я не понял, как ...

ответ

0

Я думаю, что вы в основном там, но я предлагаю использовать насмешливую структуру, такую ​​как Moq (мой личные предпочтения) или Rhino Mocks, чтобы высмеять IReportContext для проведения модульных тестов, вместо того, чтобы создавать класс Fake, например MockReportContext. (Хорошо, изучая насмешливый фреймворк, есть некоторые проблемы, но он сэкономит много фальшивого класса в дороге.)

Я бы предположил, что вы тестируете модуль, который зависит от IReportContext, поэтому вам не нужно ничего делать внутри SaveChanges(), вам просто нужно утверждать, что ваш код действительно вызывал SaveChanges() внутренне, если это предполагалось.

Here's a good overview Использование Moq с производными классами DbContext/DbSet с помощью Entity Framework.

В приведенном выше связанном обзоре, если тестовый модуль в конце тестировал метод, который внутренне вызывает SaveChanges(), он может дополнительно проверить, что SaveChanges() действительно вызывается ваш метод с линией:

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

Вы также можно было бы сделать это со своим классом MockReportContext, установив боковое свойство True внутри класса SaveChanges() и проверив его в конце вашего модульного теста, но смеющаяся структура намного более гибкая и избавит от необходимости писать дополнительные классы для модульных тестов ,

Если вы хотите избежать использования насмешливого фреймворка, то вот how to do it with fakes.

Смежные вопросы