setUp / tearDown (@ Before / @ After), почему мы нуждаемся в них в JUnit?

Я считаю, что мы все знаем, что setUp (@Before) будет выполняться до того, как любой метод тестирования и tearDown (@After) будут выполняться после метода тестирования.

Также мы знаем, что Junit создаст один экземпляр теста на тестовый метод .

мой вопрос в том, что мы можем просто переместить содержимое метода setUp в class Constructor и удалить метод setUp? существует ли какая-либо конкретная причина для сохранения метода setUp?

Эта (старая) статья лучшей практики JUnit ставит так:

Не используйте конструктор тестового случая для настройки тестового примера

Настройка тестового примера в конструкторе не является хорошей идеей. Рассматривать:

public class SomeTest extends TestCase public SomeTest (String testName) { super (testName); // Perform test set-up } } 

Представьте, что при выполнении настройки код установки генерирует IllegalStateException . В ответ JUnit выкинет AssertionFailedError , указав, что тестовый пример не может быть создан. Ниже приведен пример полученной трассировки стека:

 junit.framework.AssertionFailedError: Cannot instantiate test case: test1 at junit.framework.Assert.fail(Assert.java:143) at junit.framework.TestSuite.runTest(TestSuite.java:178) at junit.framework.TestCase.runBare(TestCase.java:129) at junit.framework.TestResult.protect(TestResult.java:100) at junit.framework.TestResult.runProtected(TestResult.java:117) at junit.framework.TestResult.run(TestResult.java:103) at junit.framework.TestCase.run(TestCase.java:120) at junit.framework.TestSuite.run(TestSuite.java, Compiled Code) at junit.ui.TestRunner2.run(TestRunner.java:429) 

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

Вместо того, чтобы настраивать данные в конструкторе, выполните тестовую настройку, переопределив setUp() . Любое исключение, setUp() в setUp() , сообщается правильно. Сравните эту трассировку стека с предыдущим примером:

 java.lang.IllegalStateException: Oops at bp.DTC.setUp(DTC.java:34) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult.protect(TestResult.java:100) at junit.framework.TestResult.runProtected(TestResult.java:117) at junit.framework.TestResult.run(TestResult.java:103) ... 

Эта трассировка стека гораздо более информативна; он показывает, какое исключение было IllegalStateException ( IllegalStateException ) и откуда. Это значительно облегчает объяснение отказа тестовой установки.

На работе мы обнаружили нечто довольно интересное, которое отвечает на ваш вопрос. Когда вы запускаете тестовый пакет, особенно большой набор тестов (200+), JUnit начинает использовать много памяти, это связано с тем, что ВСЕ тесты устанавливаются до запуска любого фактического метода тестирования.

Из-за этого мы столкнулись с «утечкой памяти» из-за этого, потому что мы использовали Spring для подключения в некоторых объектах EntityyManager JPA для наших тестов базы данных, это стало большим количеством объектов и большой объем памяти, и примерно на полпути через тесты мы получали исключения OutOfMemory ,

ИМХО, наилучшей практикой является использование setUp и tearDown для вложения ваших зависимостей и исключения из любых ссылок на все classы, это заставит ваши тесты работать быстрее и сэкономить вам много головной боли!

Надеюсь, вы узнаете из наших ошибок 🙂

Вот 3 веские причины. В итоге:

  1. Некоторые ситуации могут предпочесть отложить установку тестовых приборов как можно дольше, до того, как будет выполнен тестовый случай.

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

  3. Вы получаете лучшую диагностику, если код установки не работает в setUp (), а не в случае сбоя в конструкторе.

1. Отложите настройку приборов до момента тестирования

Дизайн для удобства использования
http://www.artima.com/weblogs/viewpost.jsp?thread=70189

… И, как выразился Эллиотт Расти Гарольд, если вы собираетесь создать новый экземпляр TestCase для каждого тестового метода, «зачем, черт возьми, с помощью метода setUp ()?» Вы можете просто использовать конструктор TestCase.

Я слышал, что Брюс Эккель отметил, что существует одно тонкое различие между созданием вашего прибора в setUp () и его созданием в конструкторе TestCase. JUnit создает все экземпляры TestCase спереди , а затем для каждого экземпляра вызывает setup (), метод тестирования и tearDown () . Другими словами, тонкая разница заключается в том, что все конструкторы вызываются в пакетном представлении спереди, тогда как метод setUp () вызывается непосредственно перед каждым тестовым методом . Но это, по-видимому, не столь полезное различие на практике.

2. Отложить настройку приборов до тех пор, пока не будут созданы все тестовые примеры

Программирование Java Extreme от ETutorial – 4.6 Настройка и срыв
http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/

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

В случаях, когда ваш тестовый пример является частью более глубокой иерархии наследования, вы можете отложить инициализацию объекта до тех пор, пока не будут полностью созданы экземпляры производных classов [test] . Это хорошая техническая причина, по которой вы можете использовать setUp () вместо конструктора для инициализации. Использование setUp () и tearDown () также полезно для целей документации, просто потому, что это может сделать код более удобным для чтения .

3. Улучшенная диагностика в случае сбоя установки

Лучшие практики JUnit (JavaWorld)
http://www.javaworld.com/jw-12-2000/jw-1221-junit.html

Настройка тестового примера в конструкторе не является хорошей идеей. …

Представьте [в коде, где настройка выполняется в конструкторе тестового случая], что при выполнении настройки код установки генерирует исключение IllegalStateException. В ответ JUnit выкинет AssertionFailedError, указав, что тестовый пример не может быть создан. …

Эта трассировка стека [исключения, созданного в установочном коде в конструкторе тестового случая], оказывается довольно неинформативной; это только указывает на то, что тестовый пример не может быть создан.

Вместо того, чтобы настраивать данные в конструкторе, выполните тестовую настройку, переопределив setUp (). Любое исключение, заданное в setUp (), сообщается правильно.

Эта трассировка стека [исключения, созданного в методе setUp () вместо конструктора тестового случая], гораздо более информативна; он показывает, какое исключение было выбрано (IllegalStateException) и откуда. Это значительно облегчает объяснение отказа тестовой установки.

Пользовательский бегун, такой как SpringJUnit4ClassRunner может потребоваться запустить некоторые коды между конструктором и методом @Before . В этом случае бегун может вводить некоторую зависимость, которой @Before методы @Before . Но инъекция зависимостей может выполняться только после создания объекта.

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

Предположим, что ваш тестовый class обернут, скажем, доступ к базе данных. После каждого теста вы хотите удалить все изменения, сделанные вашими испытаниями в db, – если вы этого не сделали, каждый тест выполняется против слегка измененной базы данных. Кроме того, любой заданный тест может увидеть другой набор изменений, если некоторые подмножества предыдущих тестов не удались. Например, предположим, что test1 выполняет вставку, test2 проверяет, что вы точно читаете размер таблицы. День 1, тест1 терпит неудачу, а 0 – правильно. День 2, тест1 преуспевает, а 1 правильный?

BTW, junit также поддерживает @BeforeClass если вы хотите выполнить глобальную настройку, а настройка и отключение являются необязательными.

Я думаю, что некоторая причина должна понравиться:

  1. Если вы переместите @Before содержимое в Constructor, это нормально, но содержимое @After, куда вы можете перейти?
  2. Различия Constructor и @ Before / @ After заключаются в том, что конструктор должен использоваться для экземпляра some для classа, @ Before / @ After предназначен для подготовки ресурсов тестового случая.
  • Разница между @Before, @BeforeClass, @BeforeEach и @BeforeAll
  • Очистка после всех тестов junit
  • Указание порядка для junit 4 тестов на уровне метода (не уровне classа)
  • Как я могу создать тестовый набор в JUnit 4?
  • Начал ли JUnit4 поддерживать заказ теста? Это намеренно?
  • @RunWith (MockitoJUnitRunner.class) против MockitoAnnotations.initMocks (это)
  • Как работает Junit @Rule?
  • Java: Является ли assertEquals (String, String) надежным?
  • Давайте будем гением компьютера.