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

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

import spock.lang.Specification

class ExampleSpec extends Specification {

    def wrapperFunction(Closure cl) {
        try {
            cl()
        } finally {
            // do custom stuff
        }
    }

    def "test wrapped in closure"() {
        wrapperFunction {
            expect:
            1 == 1
            println "will not execute!"
        }
    }
}

Каков наилучший подход к созданию и удалению ресурса внутри спок-теста.

setup() и cleanup() не являются жизнеспособными решениями, поскольку создание и удаление должны быть возможны в произвольных точках внутри метода объекта.

1
Th 00 mÄ s 8 Ноя 2019 в 18:56
Трудно догадаться, что вы тестируете в этом примере. Вы пытаетесь утверждать, что cl вызывается?
 – 
jaco0646
8 Ноя 2019 в 19:09
Я предполагаю, что ошибка что-то вроде того, что Спок жалуется на структуру здесь? Подход без оставшихся умных опций может заключаться в перемещении expect: и написании обычных утверждений внутри этого замыкания.
 – 
cfrick
8 Ноя 2019 в 21:44
Что это за ресурсы?
 – 
Yuri G
9 Ноя 2019 в 00:01
1
Теперь, что касается вашей НАСТОЯЩЕЙ ситуации: почему вы вообще беспокоитесь об этом, мне интересно еще больше? На месте выполнения теста эти фасады для макетов сервера очень дешевы, зачем кому-то когда-либо хотеть удалять их явно, кроме того, что JVM все равно будет делать в конце жизни теста (который довольно короткий, пока JUnit на самом деле запуск материала Spock, и он охватывает отдельный экземпляр тестового класса для каждого выполняемого метода @test)? Фактическая серверная реализация макетов не сильно отличается, она довольно существенна, а потребление ресурсов незначительно.
 – 
Yuri G
14 Ноя 2019 в 00:12
2
Имея тот факт, что макеты можно переопределить на сервере WireMock, я не понимаю, зачем вообще удалять каждый отдельный макет после (не говоря уже во время) каждого отдельного метода тестирования? Просто сбросьте все операции в общем наборе тестов tearDown, и все будет в порядке. Все это говорит о том, что вы не чувствуете, что перепроектируете все это просто из НИЧЕГО?
 – 
Yuri G
14 Ноя 2019 в 00:17

1 ответ

Вы можете использовать блоки setup и cleanup внутри тестового примера (метод функции) следующим образом:

class ReleaseResourcesSpec extends Specification {
    void 'Resources are released'() {
        setup:
        def stream = new FileInputStream('/etc/hosts')

        when:
        throw new IllegalStateException('test')

        then:
        true

        cleanup:
        stream.close()
        println 'stream was closed'
    }
}

Код из блока cleanup всегда выполняется, даже если тест не пройден или если есть какое-либо исключение. См. результат приведенного выше примера: введите здесь описание изображения

Таким образом, это похоже на методы setup() и cleanup(), но в этом случае у вас может быть разная настройка и код очистки для каждого метода функции.

3
cgrim 9 Ноя 2019 в 16:08
Действительно жизнеспособное решение, которое мы в настоящее время используем в аналогичной форме. Необходимость хранить ресурс внутри выделенной переменной и дополнительный код, необходимый для освобождения промежуточного ресурса (который нам иногда нужен), заставили нас задать вопрос выше. @cgrim любым способом, чтобы избежать разделения раздела setup: и cleanup: и создать что-то, что больше похоже на этот шаблон, используя шаблон
 – 
Th 00 mÄ s
9 Ноя 2019 в 17:44