Подтвердить что ты не робот

JUnit - должен ли я присваивать null ресурсам в tearDown, которые были созданы в setUp?

Сейчас я читаю одну книгу о JUnit, и автор советует обнулить ресурсы в методе tearDown. Зачем? Разве это не работа GC? Может ли это серьезно навредить?

Давайте рассмотрим пример следующим образом:

public class SomeTest extends TestCase {
  Vector vector;
  List<Object> list;  

  protected void setUp() {
    vector = new Vector();
    list = new ArrayList<Object>();
  }

  // messing with resources
  // adding, deleting, testing whatever

  protected void tearDown() {
    vector = null;
    list = null;
  }
}

Как вы думаете? Требуется ли этот код в tearDown?

4b9b3361

Ответ 1

Да, это действительно действительно необходимо.

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

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

Ответ 2

Это зависит от того, что вы считаете ресурсом. В то время как кучное пространство является ресурсом, вы, вероятно, можете уйти с очисткой GC после вас (YMMV).

Вещи, которые могут вызвать проблемы, - это Closable, такие как соединения с базой данных/открытые файлы и потоки и т.д., которые следует всегда закрывать после использования, чтобы предотвратить гадости в длинном коде.

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

Ответ 3

Тесты стиля JUnit 4.x и комплекты тестов обрабатывают это иначе, чем тестовые комплекты JUnit 3.x.

TL; DR: вы должны устанавливать поля в null в тестах стиля JUnit3, но , которые вам не нужны в тестах стиля JUnit4.

С помощью тестов стиля JUnit 3.x TestSuite содержит ссылки на другие объекты Test (которые могут быть объектами TestCase или другими объектами TestSuite). Если вы создадите пакет с большим количеством тестов, тогда будут жесткие ссылки на все объекты leaf TestCase для всего прогона самого удаленного набора. Если некоторые из объектов TestCase выделяют объекты в setUp(), которые занимают много памяти, а ссылки на эти объекты хранятся в полях, которые не установлены на null в tearDown(), тогда у вас может быть проблема с памятью.

Другими словами, для тестов стиля JUnit 3.x спецификация тех тестов для запуска ссылок на фактические объекты TestCase. Любые объекты, доступные из объекта TestCase, будут храниться в памяти во время тестового прогона.

Для тестов стиля JUnit 4.x в спецификации, для запуска которых используются Description объекты. Объект Description - это объект значения, который указывает, что нужно запускать, но не как его запустить. Тестирование выполняется объектом Runner, который принимает Description теста или набора и определяет, как выполнить тест. Даже уведомление о статусе теста для тестового слушателя использует объекты Description.

По умолчанию для тестовых примеров JUnit4 по умолчанию JUnit4 хранится ссылка на тестовый объект только на время прогона этот тест. Если вы используете пользовательский бегун (через аннотацию @RunWith), этот бегун может или не может ссылаться на тесты в течение более длительных периодов времени.

Возможно, вам интересно, что произойдет, если вы включите тестовый класс в стиле JUnit3 в стиле JUnit4 Suite? JUnit4 вызовет new TestSuite(Class), который создаст отдельный экземпляр TestCase для каждого тестового метода. Бегун будет хранить ссылку на TestSuite на весь период тестового прогона.

Короче говоря, если вы пишете тесты в стиле JUnit4, не беспокойтесь о том, чтобы установить поля тестового случая на null в результате срыва (конечно, свободные ресурсы). Если вы пишете тесты типа JUnit3, которые выделяют большие объекты в setUp() и сохраняют эти объекты в полях TestCase, рассмотрите установку полей null.