Entity Framework 4.1 модульные тесты интеграции - PullRequest
1 голос
/ 17 августа 2011

Во-первых, несколько предостережений:

Мы строим систему малого / среднего размера, срок жизни которой ожидается 2-5 лет (относительно короткий).Система разрабатывается с использованием Entity Framework 4.1, Code First, MVC3.Мы пытаемся подтолкнуть нашу команду к юнит-тестированию / TDD.Это то, чего мы еще не сделали, но мы осознаем его ценность, поэтому делаем шаги в этом направлении.

Учитывая все это, мы решили создать модульные тесты с помощью встроенной среды тестирования Visual Studio 2010.Мы НЕ используем шаблон репозитория или макеты.Это позволяет снизить сложность и время, затрачиваемое на создание модульных тестов.Каждый модульный тест на самом деле является скорее интеграционным тестом - у нас есть «тестовая» база данных, которая инициализируется при каждом запуске тестов, и каждый тест использует те же контроллеры, которые используются представлениями, чтобы максимально приблизиться к реальному миру.поведение системы.

Комментируя или отвечая на этот вопрос, , пожалуйста, не атакуйте этот подход .Мне хорошо известно, что это не TDD в чистом виде и не идеальный шаблон для тестирования единиц работы.Мы делаем это таким образом, чтобы намокнуть ногами с помощью этой технологии, и стараемся получить максимальную отдачу от затраченного времени с точки зрения затрат времени на создание модульных тестов.

Проблема:

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

[TestMethod]
public void Edit_Post_Saves_OperatingCompany_In_DB_When_OperatingCompany_Is_Valid()
{   
    OperatingCompany opco = new OperatingCompany();
    opco.Name = "OpCo - Edit Post - Valid - DB Save";
    controller = new OperatingCompanyController();
    controller.Create(opco);

    Guid opcoid = opco.Id;

    controller = new OperatingCompanyController();
    opco = (OperatingCompany) ((ViewResult)controller.Edit(opcoid)).Model;
    opco.Name = "Edit - OpCo - Edit Post - Valid - DB Save";

    controller = new OperatingCompanyController();
    HelperMethods.AddValidationResultsToModelState(opco, controller);
    controller.Edit(opco);

    controller = new OperatingCompanyController();
    ViewResult result = controller.Index();

    Assert.IsTrue(((IEnumerable<OperatingCompany>)result.Model).Contains(opco));
}

Ошибка, которую мы получаем:На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker.

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

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

Вопрос:

Есть ли какой-нибудь лучший способ выполнить этот тип интеграционного теста с нашими контроллерами?

1 Ответ

0 голосов
/ 18 августа 2011

Может быть, вы можете попробовать создать новый экземпляр opco, прежде чем передать его в действие Edit (post). Для упрощения создания копии вы можете использовать AutoMapper, например:

Mapper.CreateMap<OperatingCompany, OperatingCompany>();
opco = Mapper.Map<OperatingCompany, OperatingCompany>(opco);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...