На самом деле, это возможно в споке, если ваш код может быть статическим.
Чтобы выполнить однократную инициализацию (раскрутить контейнер, запустить тестовый кластер zookeeper или что-то еще), просто создайте статический одноэлементный держательнапример:
class Postgres {
private static PostgresContainer container
static void init() {
if (container != null)
return
container = new PostgresContainer()
container.start()
}
static void destroy() {
if (container == null)
return
container.stop()
container = null
}
}
Тогда вам нужен абстрактный класс для интеграционных тестов, например:
class IntegrationTest extends Specification {
def setup() {
init()
}
static void init () {
Postgres.init()
}
def cleanup() {
// do whatever you need
}
static void destroy() {
Postgres.destroy()
}
}
Теперь очистка немного сложная - особенно если у вас есть некоторыепотоки, не являющиеся демонами, не позволяющие завершить работу jvm.Это может привести к зависанию вашего набора тестов.Вы можете использовать shutdownHoook
s или использовать механизм spock AbstractGlobalExtension
.Вы можете выполнить некоторый код сразу после того, как спок выполнит все спецификации.Для нашего сценария postgres у нас будет что-то вроде:
class IntegrationTestCleanup extends AbstractGlobalExtension {
@Override
void stop() {
IntegrationTest.destroy()
}
}
Существует одна недостающая головоломка, чтобы она работала - вам нужно предоставить специальный файл в src/test/resources/META-INF.services/org.spockframework.runtime.extension.IGlobalExtension
, который ссылается на ваше расширение.Этот файл должен содержать одну строку, указывающую на ваше расширение, например com.example.IntegrationTestCleanup
. Это заставит спока его распознать.Имейте в виду, что он будет выполняться в выделенном потоке спока.
Я понимаю, что это как бы дублирует принятый ответ, но недавно я пытался выполнить глобальную очистку в споке, поэтому подумал, что это может быть полезно.