Сбой теста JUnit - жалоба на отсутствующие данные, которые были только что вставлены - PullRequest
3 голосов
/ 31 мая 2010

У меня чрезвычайно странная проблема в моих тестах JUnit, которую я просто не могу зафиксировать. У меня есть многомодульный Java-проект веб-приложения с довольно стандартной структурой (DAO, сервисная служба и т. Д.). В рамках этого проекта у меня есть «основной» проект, который содержит некоторый абстрактный код установки, который вставляет тестового пользователя вместе с необходимыми элементами для пользователя (в данном случае «предприятие», поэтому пользователь должен принадлежать предприятию, и это принудительно выполняется). на уровне базы данных)

Пока все довольно просто ... но вот тут начинается странность

  1. некоторые тесты не запускаются и выдают исключение из базы данных, когда он жалуется, что пользователь не может быть вставлен, потому что предприятие не существует. Но это только что создало предприятие в предыдущей строке кода! И не было ошибок при вставке предприятия.
  2. Еще страннее, если этот тестовый класс запускается сам по себе, все работает отлично. Только когда тест выполняется как часть проекта, он проваливается!
  3. И точно такой же абстрагированный код был запущен более чем 10 тестами, прежде чем тот, который потерпел неудачу!
  4. F

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

  • Использование JUnit 4.4, Spring 2.5.6, iBatis 2.3.0, Postgresql 8.3
  • Переключение на org.springframework.jdbc.datasource.DriverManagerDataSource из org.apache.commons.dbcp.BasicDataSource изменило проблему. Используя DriverManagerDataSource, тесты работают впервые, но теперь внезапно большая часть данных не возвращается в базу данных! Это оставляет все позади. Все без ошибок
  • Тесты не выполняются при запуске через Eclipse & Maven

Пожалуйста, попросите любую информацию, которая может помочь мне решить мою проблему!

Обновление: Я включил ведение журнала до макс. Есть только одно небольшое различие между этим тестом, который проваливается, и другим, точно так же, как он проходит успешно. Разница выделена. После возникновения ошибки я вижу ряд строк «Создание [java.util.concurrent.ConcurrentHashMap]», а затем начинается код обработки ошибки

Ответы [ 3 ]

1 голос
/ 28 апреля 2011

Я столкнулся с подобной проблемой, используя Junit4 и Spring. Мне пришлось добавить @Transactional к моим методам тестирования, чтобы считывать данные из базы данных перед фиксацией.

1 голос
/ 31 мая 2010

Это сложная проблема для решения SO, но я собираюсь сделать дикое предположение, основываясь на деталях, которые вы дали.

Гипотеза: все вставки в тесте происходят в транзакции, которая откатывается. (Вот почему BasicDataSource оставляет базу данных чистой - она ​​откатывается в конце). Когда это перестает происходить (с помощью DriverManagerDataSource), тест проходит, но база данных не откатывается.

Это говорит о том, что хотя "оно только что создало предприятие в предыдущей строке кода!" транзакцию можно откатить, чтобы удалить запись.

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

РЕДАКТИРОВАТЬ: Из вашего редактирования кажется, что по какой-то причине при неудачном тесте вы получаете новое соединение с базой данных. Это соответствует моему сценарию выше, но также может быть объяснено, если указать, что по какой-то причине в этот момент в коде появляется новая транзакция, когда тест выполняется как часть всего проекта. Новая транзакция не видит вставку корпоративной записи, которая происходит в другой транзакции, и транзакция остается открытой и незафиксированной. Чтобы проверить это, нужно установить максимальный уровень изоляции транзакций, чтобы ничто не могло сканировать корпоративную таблицу, пока в ней есть транзакция. Тогда ваш код заблокируется, если этот сценарий верен.

Дальнейшее РЕДАКТИРОВАНИЕ: я имею в виду под финализатором, который вызывает close, что-то вроде этого:

 public class SomeConnectionWrapper {
      private Connection dbConnection;

      protected void finalize() {
           dbConnection.close();
      }
 }

Если SomeConnectionWrapper собрана сборщиком мусора и соединение закрыто, ваш пул соединений с базой данных вернет другое соединение.

0 голосов
/ 18 июня 2010

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

Этот тестовый класс расширен от базового тестового класса, который определил все связанные с Spring аннотации установки, такие как @RunWith и @ContextConfiguration. По какой-то причине этот тестовый класс переопределил атрибуты @RunWith и @ContextConfiguration, и как только я их удалил, все снова заработало. Другая странная вещь в этом тестовом классе заключалась в том, что я использовал @Ignore для каждого теста в нем (он содержал несколько старых тестов).

Так что ... если у кого-нибудь возникнет эта странная проблема, вы можете попробовать удалить лишние аннотации, чтобы исправить ее

...