Как использовать библиотеку "Pex and Moles" с Entity Framework?
Это сложный вопрос, потому что не так уж много людей используют Pex & Moles или что-то вроде этого (хотя Pex - действительно отличный продукт - намного лучше, чем любой другой инструмент для модульного тестирования)
У меня есть проект данных, который имеет очень простую модель только с одной сущностью (DBItem
). Я также написал DBRepository
в рамках этого проекта, который манипулирует этой моделью EF. В репозитории есть метод GetItems()
который возвращает список элементов бизнес-уровня (BLItem
) и выглядит примерно так (упрощенный пример):
public IList<BLItem> GetItems()
{
using (var ctx = new EFContext("name=MyWebConfigConnectionName"))
{
DateTime limit = DateTime.Today.AddDays(-10);
IList<DBItem> result = ctx.Items.Where(i => i.Changed > limit).ToList();
return result.ConvertAll(i => i.ToBusinessObject());
}
}
Так что теперь я хотел бы создать несколько модульных тестов для этого конкретного метода. Я использую Pex & Moles. Я создал мои родинки и заглушки для контекста моего объекта EF.
Я хотел бы написать параметризованный модульный тест (я знаю, что впервые написал свой производственный код, но мне пришлось, так как я тестирую Pex & Moles), который проверяет, что этот метод возвращает действительный список элементов.
Это мой тестовый класс:
[PexClass]
public class RepoTest
{
[PexMethod]
public void GetItemsTest(ObjectSet<DBItem> items)
{
MEFContext.ConstructorString = (@this, name) => {
var mole = new SEFContext();
};
DBRepository repo = new DBRepository();
IList<BLItem> result = repo.GetItems();
IList<DBItem> manual = items.Where(i => i.Changed > DateTime.Today.AddDays(-10));
if (result.Count != manual.Count)
{
throw new Exception();
}
}
}
Затем я запускаю Pex Explorations для этого конкретного параметризованного модульного теста, но получаю, что границы пути ошибки превышены. Пекс начинает этот тест, предоставляя null
к этому методу испытаний (так items = null
). Это код, который запускает Pex:
[Test]
[PexGeneratedBy(typeof(RepoTest))]
[Ignore("the test state was: path bounds exceeded")]
public void DBRepository_GetTasks22301()
{
this.GetItemsTest((ObjectSet<DBItem>)null);
}
Это был дополнительный комментарий, предоставленный Пексом:
Тестовый пример был слишком длинным для этих входных данных, и Пекс прекратил анализ. Обратите внимание: метод Oblivious.Data.Test.Repositories.TaskRepositoryTest.b__0 был вызван 50 раз; пожалуйста, убедитесь, что код не застрял в бесконечном цикле или рекурсии. В противном случае нажмите "Установить MaxStack=200" и снова запустите Pex.
Обновить атрибут [PexMethod(MaxStack = 200)]
Вопрос
Я делаю это правильно или нет? Должен ли я использовать заглушку EFContext вместо? Нужно ли добавлять дополнительные атрибуты в метод тестирования, чтобы Moles host работал (я не уверен, что сейчас). Я бегу только Pex & Moles. Нет теста VS или nUnit или что-то еще.
Думаю, мне следует установить ограничение на Pex, сколько элементов он должен предоставить для этого конкретного метода тестирования.
3 ответа
Moles не предназначен для тестирования частей вашего приложения, которые имеют внешние зависимости (например, доступ к файлам, доступ к сети, доступ к базе данных и т. Д.). Вместо этого, Moles позволяет вам смоделировать эти части вашего приложения, чтобы вы могли проводить истинное модульное тестирование на частях, которые не имеют внешних зависимостей.
Поэтому я думаю, что вы должны просто высмеивать ваши объекты EF и запросы, например, создавая списки в памяти и используя методы запросов, возвращающие поддельные данные из этих списков на основе любых критериев, которые имеют отношение к делу.
Вам следует использовать шаблон репозитория Entity Framework: http://www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx
Я только начинаю справляться с pex также... мои проблемы окружили меня, желая использовать его с moq;)
тем не мение...
У меня есть несколько методов, похожих на ваш, которые имеют ту же проблему. Когда я увеличил максимум, они ушли. Предположительно pex был удовлетворен тем, что он достаточно исследовал ветви. У меня есть методы, где мне также пришлось увеличить время ожидания проверки кода.
Одна вещь, которую вы, вероятно, должны сделать правильной, это передача всех зависимых объектов в качестве параметров... т.е. не создавать экземпляр репозитория в методе, а передавать его.
Общая проблема, с которой вы столкнулись, заключается в том, что вы создаете большие объекты в своем методе. Я делаю то же самое в своих классах DAL, но тогда я не пытаюсь проводить их модульное тестирование в изоляции. Я создаю наборы данных и использую это для проверки своего кода доступа к данным.
Я использую pex в своей бизнес-логике и объектах.
Если бы я попытался проверить мой код DAL, то для передачи кода данных в методы мне нужно было бы использовать IOC, что сделало бы возможным тестирование, так как вы можете имитировать контекст данных.