Поблочное тестирование с EF4 “Код Сначала” и Репозиторий

Я пытаюсь разобраться с Поблочным тестированием очень простой ASP.NET тестовое приложение MVC, я создал использование Кода, Сначала приближаются в последнем EF4 CTP. Я не очень опыт с Поблочным тестированием / дразнящий и т.д.

Это - мой класс Репозитория:

public class WeightTrackerRepository
{
    public WeightTrackerRepository()
    {
        _context = new WeightTrackerContext();
    }

    public WeightTrackerRepository(IWeightTrackerContext context)
    {
        _context = context;
    }

    IWeightTrackerContext _context;

    public List<WeightEntry> GetAllWeightEntries()
    {
        return _context.WeightEntries.ToList();
    }

    public WeightEntry AddWeightEntry(WeightEntry entry)
    {
        _context.WeightEntries.Add(entry);
        _context.SaveChanges();
        return entry;
    }
}

Это - IWeightTrackerContext

public interface IWeightTrackerContext
{
    DbSet<WeightEntry> WeightEntries { get; set; }
    int SaveChanges();
}

... и его реализация, WeightTrackerContext

public class WeightTrackerContext : DbContext, IWeightTrackerContext
{
    public DbSet<WeightEntry> WeightEntries { get; set; }
}

В моем тесте у меня есть следующее:

[TestMethod]
public void Get_All_Weight_Entries_Returns_All_Weight_Entries()
{
    // Arrange
    WeightTrackerRepository repos = new WeightTrackerRepository(new MockWeightTrackerContext());

    // Act
    List<WeightEntry> entries = repos.GetAllWeightEntries();

    // Assert
    Assert.AreEqual(5, entries.Count);
}

И мой MockWeightTrackerContext:

class MockWeightTrackerContext : IWeightTrackerContext
{
    public MockWeightTrackerContext()
    {
        WeightEntries = new DbSet<WeightEntry>();
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("01/06/2010"), Id = 1, WeightInGrams = 11200 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("08/06/2010"), Id = 2, WeightInGrams = 11150 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("15/06/2010"), Id = 3, WeightInGrams = 11120 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("22/06/2010"), Id = 4, WeightInGrams = 11100 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("29/06/2010"), Id = 5, WeightInGrams = 11080 });
    }

    public DbSet<WeightEntry> WeightEntries { get;set; }

    public int SaveChanges()
    {
        throw new NotImplementedException();
    }
}

Моя проблема происходит, когда я пытаюсь создать некоторые данные тестирования, поскольку я не могу создать a DbSet<> поскольку это не имеет никакого конструктора. Я получаю чувство, что я рявкаю неправильное дерево со своим целым подходом, пытающимся дразнить мой контекст. Любой совет нравился бы этому полному новичку поблочного тестирования.

49
задан DavidGouge 11 August 2010 в 21:53
поделиться

1 ответ

Вы создаете DbSet с помощью фабричного метода Set () в контексте, но вам не нужна зависимость от EF в модульном тесте. Следовательно, вам необходимо реализовать заглушку DbSet с использованием интерфейса IDbSet или заглушку с использованием одной из фреймворков Mocking, таких как Moq или RhinoMock. Предполагая, что вы написали свою собственную заглушку, вам нужно просто добавить объекты WeightEntry во внутренний хэш-набор.

Возможно, вам повезет больше узнать о модульном тестировании EF, если вы будете искать ObjectSet и IObjectSet. Это аналоги DbSet до выпуска первого кода CTP, и о них написано гораздо больше с точки зрения модульного тестирования.

Вот отличная статья на MSDN, в которой обсуждается тестируемость кода EF. Он использует IObjectSet, но я думаю, что он по-прежнему актуален.

В ответ на комментарий Дэвида я добавляю это дополнение ниже, поскольку оно не помещается в -комментарии. Не уверены, что это лучший способ для ответов на длинные комментарии?

Вам следует изменить интерфейс IWeightTrackerContext, чтобы он возвращал IDbSet из свойства WeightEntries, а не конкретный тип DbSet. Затем вы можете создать MockContext либо с помощью фреймворка для имитации (рекомендуется), либо с помощью собственной настраиваемой заглушки.Это вернет StubDbSet из свойства WeightEntries.

Теперь у вас также будет код (например, пользовательские репозитории), который зависит от IWeightTrackerContext, который в процессе производства вы передадите в свой Entity Framework WeightTrackerContext, который будет реализовывать IWeightTrackerContext. Обычно это делается посредством внедрения конструктора с использованием инфраструктуры IoC, такой как Unity. Для тестирования кода репозитория, который зависит от EF, вы должны передать свою реализацию MockContext, чтобы тестируемый код считал, что он обращается к «реальным» EF и базой данных, и ведет себя (надеюсь), как ожидалось. Поскольку вы удалили зависимость от изменяемой внешней системы БД и EF, вы можете надежно проверять вызовы репозитория в своих модульных тестах.

Большая часть фреймворков имитаторов предоставляет возможность проверять вызовы имитирующих объектов для тестирования поведения. В приведенном выше примере ваш тест на самом деле тестирует только функциональность DbSet Add, которая не должна вас беспокоить, поскольку у MS будут модульные тесты для этого. Что вы хотели бы знать, так это то, что вызов Add on DbSet был сделан из кода вашего собственного репозитория, если это необходимо, и именно здесь на помощь приходят фреймворки Mock.

Извините, я знаю, что это много для переваривания, но если вы прочтете эту статью, и многое станет яснее, поскольку Скотт Аллен намного лучше объясняет эти вещи, чем я :)

48
ответ дан 7 November 2019 в 11:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: