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?
Ответы
Ответ 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
.