Как вы получаете JUnit для моделирования нескольких открытых вкладок / окон, но только один сеанс - PullRequest
1 голос
/ 08 июля 2011

Я пишу модульные тесты для Spring Framework 2.5, используя JUnit.Более конкретно, я использую MockHttpServletRequest для тестирования моих контроллеров.Я столкнулся с проблемой, тестируя определенный сценарий.

Приложение редактировало объекты, сохраненные в Hibernate.Объекты работают примерно так:

Class Workflow {
  ... various properties and methods
  Long workflowId;  // primary key for this object
  Long subclassId;  // foreign key to another class
  String subclassType; // what kind of other class?
}

Class Request {
  .. various other properties and methods
  Long subclassId; // primary key for this object
  Long workflowId; // foreign key to Workflow
}

Рабочий процесс всегда привязан к одному, и только один, Запрос и Запрос всегда привязан к одному и только одному Рабочему процессу.Однако существует несколько объектов / таблиц, с которыми Workflow может ссылаться, поэтому subclassType должен отслеживать, какую другую таблицу искать. Таким образом, это немного похоже на запрос, наследуемый от / внедряющий Workflow, но база данных хранит их вотдельные таблицы, поэтому Java была реализована как отдельные классы.

Я не писал этот беспорядок.Я поддерживаю это.И он широко используется, с несколькими различными приложениями и типами subclassTypes, поэтому существуют ограничения на то, сколько «очистки» я могу сделать.

Рассматриваемое веб-приложение помещало объект Workflow в HttpSession, но редактировал Запрос вформа.Когда кто-то открывал несколько окон / вкладок с разными запросами в каждом окне, объект рабочего процесса из последнего открытого перезаписывал любые ранее открытые (сеансы привязаны к файлам cookie, только один набор файлов cookie для домена, совместно используемыйВСЕ окна в веб-браузере).Если они отправили форму для первого Запроса, объект Workflow из последнего (извлеченного из HttpSession) был записан с отправленным Запросом (НЕ правильным), что повредило данные в базе данных.

Мыв итоге возникли запросы, к которым было подключено несколько рабочих процессов, и запросы, к которым не было подключено ни одного рабочего процесса.

Очевидным решением было переписать приложение, чтобы оно никогда не сохраняло рабочий процесс в HttpSession.workflowId - одно из полей в Запросе;мы сохранили это в форме через скрытое поле.Да, мы чаще обращаемся к базе данных, но мы не пересекаем наши записи.

Такова ситуация.Теперь вопрос: как вы смоделируете это в JUnit?Чтобы никто в будущем не столкнулся с этой ситуацией снова?

Мы используем MockHttpServletRequest, подключая значения форм и отправляя их, используя AnnotationMethodHandlerAdapter и объект Controller.Как пример:

    MockHttpServletRequest request = new MockHttpServletRequest();
    MockHttpServletResponse response = new MockHttpServletResponse();
    AnnotationMethodHandlerAdapter handler = new AnnotationMethodHandlerAdaptor();
    RequestFormController controller = new RequestFormController();

    request.setMethod("GET");
    request.setRequestURI("/EditRequest.do"); // handled by the RequestFormController

    request.setParameter("wfId", Long.toString(wfid)); // wfId is the workflow ID of a valid Workflow with an attached Request
    ModelAndView mv = handler.handle(request, response, controller);

    request.setParameter("wfId", mv.getModel().get("wfId");
    request.setParameter("requestText", "blah blah blah");

    request.setMethod("POST");
    request.setRequestURI("/UpdateRequest.do"); // handled by the RequestFormController
    mv = handler.handle(request, response, controller);

Это все довольно просто, Spring / JUnit.Проблема в том, что для открытия чего-либо в двух разных вкладках / окнах вам нужно иметь два разных запроса, каждый из которых имеет свой собственный HttpSession.Однако в веб-браузере эти два разных запроса используют одни и те же файлы cookie, что означает, что они используют одну и ту же информацию сеанса.Как заставить JUnit смоделировать это?

Я могу скопировать куки-файлы из одного в другой, но это не выдает ошибку.MockHttpServletRequest по-прежнему хранит информацию HttpSession отдельно.Я с трудом копирую атрибуты HttpSession из одного в другой.Поскольку я так и сделал, я не могу понять, что это также раскрывает ошибку.

Есть предложения?Это очень реальная проблема, и MockHttpServletRequest и все другие связанные с JUnit вещи, которые мы делаем, точно не моделируют реальный мир Tomcat и веб-браузеров.

Peace.

1 Ответ

0 голосов
/ 08 июля 2011

При написании теста вы можете создать сеанс explicity и настроить все запросы на использование одного и того же сеанса.

MockHttpSession session = new MockHttpSession();
request.setSession(session);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...