Как использовать библиотеку Pex and Moles с Entity Framework?

Это непросто, потому что не так уж много людей используют Pex & Moles или около того (хотя Pex - действительно отличный продукт - намного лучше, чем любой другой инструмент модульного тестирования)

У меня есть проект Data, который имеет очень простую модель всего с одним объектом (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 для этого конкретного параметризованного модульного теста, но получаю сообщение об ошибке Превышены границы пути. Pex начинает этот тест, предоставляя 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);
}

Это был дополнительный комментарий от Pex:

Тестовый пример длился слишком долго для этих входных данных, и Pex остановил анализ. Обратите внимание: метод Oblivious.Data.Test.Repositories.TaskRepositoryTest.b__0 был вызван 50 раз; пожалуйста, убедитесь, что код не застревает в бесконечном цикле или рекурсии. В противном случае нажмите «Установить MaxStack = 200» и снова запустите Pex.

Обновить атрибут [PexMethod (MaxStack = 200)]

Вопрос

Правильно я это делаю или нет? Должен ли я использовать вместо него заглушку EFContext? Нужно ли мне добавлять дополнительные атрибуты в метод тестирования, чтобы хост Moles работал (сейчас я не уверен). Я бегаю только Pex & Moles. Ни теста VS, ни nUnit, ни чего-либо еще.

Думаю, мне, вероятно, следует установить для Pex какое-то ограничение на количество элементов, которые он должен предоставить для этого конкретного метода тестирования.


person Robert Koritnik    schedule 21.09.2010    source источник
comment
Я использовал только Moles, но если вы еще этого не сделали, вы можете разместить этот вопрос на форумах Pex и Moles по адресу social.msdn.microsoft.com/Forums/en-US/pex/threads   -  person Matt    schedule 01.10.2010


Ответы (3)


Moles не предназначен для тестирования частей вашего приложения, которые имеют внешние зависимости (например, доступ к файлам, доступ к сети, доступ к базе данных и т. Д.). Вместо этого Moles позволяет имитировать эти части вашего приложения, чтобы вы могли проводить истинное модульное тестирование тех частей, которые не имеют внешних зависимостей.

Поэтому я думаю, вам следует просто имитировать свои объекты и запросы EF, например, создавая списки в памяти и заставляя методы запросов возвращать поддельные данные из этих списков на основе любых подходящих критериев.

person Tonderum Conundrum    schedule 12.11.2010

Я только начинаю разбираться с pex ... мои проблемы окружали меня, желая использовать его с moq;)

так или иначе ...

У меня есть несколько методов, похожих на ваш, с той же проблемой. Когда я увеличил максимум, они ушли. Предположительно pex был удовлетворен тем, что достаточно исследовал ветви. У меня есть методы, в которых мне также пришлось увеличить тайм-аут при проверке контракта кода.

Одна вещь, которую вы, вероятно, должны сделать, это передать все зависимые объекты в качестве параметров ... т.е. не создавать экземпляр репо в методе, а передавать его.

Общая проблема заключается в том, что вы создаете экземпляры больших объектов в своем методе. Я делаю то же самое в своих классах DAL, но тогда я не пытаюсь тестировать их изолированно. Я создаю наборы данных и использую их для проверки своего кода доступа к данным.

Я использую pex в своей бизнес-логике и объектах.

Если бы я попытался проверить свой идентификатор кода DAL, мне пришлось бы использовать IOC для передачи контекста данных в методы, что затем сделало бы тестирование возможным, поскольку вы можете имитировать контекст данных.

person John Nicholas    schedule 04.10.2010
comment
Но разве не для этого нужны окурки и родинки? Заглушки должны создавать мой контекст, чтобы он работал, а Moles позволяли мне вводить любые данные, которые мне нужны. - person Robert Koritnik; 06.10.2010
comment
да, но если вы проектируете свои объекты так, чтобы передавать зависимые объекты, тогда жизнь в целом становится намного проще. Затем вы можете указать pex, какой из передаваемых объектов вы хотите протестировать, и внезапно он не тратит время на попытки выяснить, как работает контекст данных. IOC - это дизайнерское решение, которое вы не должны пытаться включить позже. Насколько я могу судить, документация по PEX предлагает вам это сделать. - person John Nicholas; 06.10.2010

Вам следует использовать шаблон репозитория Entity Framework: http://www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx

person Ricardo Rodrigues    schedule 06.11.2010