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

Когда примечание Spock @Shared должно быть предпочтительнее статического поля?

Нечего добавить, весь вопрос в заголовке.

Рассмотрим эти два экземпляра класса Foo, используемые в спецификации Spock.

@Shared Foo foo1 = new Foo()

static Foo foo2 = new Foo()

В целом, я знаю идею аннотации @Shared, но я думаю, что лучше использовать языковые функции, которые в этом случае будут полем static.

Существуют ли какие-либо конкретные случаи, в которых следует выбирать друг друга или это скорее вопрос вкуса?

4b9b3361

Ответ 1

Спок - это все о выразительности и ясности.

Статический - это ключевое слово Java, которое отображает только внутренние элементы класса (это поле для всех экземпляров одинаково)

@Shared - это функция Spock, которая говорит читателю, что эта переменная одинакова для всех методов объектов. Это инструкция специально для unit test и делает unit test более понятным для читателя.

То же самое можно сказать и для основных блоков Спока. Если вы думаете об этом, они ничего не меняют в коде.

public void myScenario(){
  int a = 2 + 3;
  assertEquals(5,a);
}

public void "simple addition scenario"(){
  when: "I add two numbers"
    int a = 2 +3

  then: "I expect the correct result"
  a == 5
}

Оба модульных теста выполняют технически то же самое. Второе, однако, более четко показывает намерение. Знаки , когда: и , а затем: ничего не делают с кодом, кроме уточнения его намерения.

Итак, чтобы подвести итог, @Shared делает тест более удобочитаемым. (См. Также @Issue, @Title и т.д., Они существуют с той же целью)

Ответ 2

В отличие от JUnit, где вам нужно объявить переменную поля static и присвоить ей значение в

@BeforeClass
public static void setupClass()

поэтому он был инициализирован только один раз на тестовый набор (не каждый метод), в Spock вы можете использовать переменную поля экземпляра и аннотировать его с помощью @Shared.

Рассмотрим следующий пример:

class SharedTestSpec extends spock.lang.Specification {

    @Shared
    def shared = shared()

    def shared() {
        "I came from ${this.class.simpleName}"
    }

    def 'Test one'() {
        given:
            println("test one, shared: $shared")
        expect: true
    }

    def 'Test two'() {
        given:
            println("test two, shared: $shared")
        expect: true

    }
}

class SubclassSpec extends SharedTestSpec {

    @Override
    def shared() {
        println("They've got me!")
        "I came from ${this.class.simpleName}"
    }
}

Запуск SubclassSpec дает вам следующий результат:

test one, shared: I came from SubclassSpec
test two, shared: I came from SubclassSpec
They've got me!

Невозможно объяснить порядок печати, но это из-за AST.

Ответ 3

Как более исчерпывающий подход, здесь приведен пример теста с выходами:

@Unroll
class BasicSpec extends Specification {

    int initializedVariable

    int globalVariable = 200

    static int STATIC_VARIABLE = 300

    @Shared
    int sharedVariable = 400

    void setup() {
        initializedVariable = 100
    }

    void 'no changes'() {
        expect:
            printVariables()
            /*
            initializedVariable: 100
            globalVariable: 200
            STATIC_VARIABLE: 300
            sharedVariable: 400
             */
    }

    void 'change values'() {
        setup:
            initializedVariable = 1100
            globalVariable = 1200
            STATIC_VARIABLE = 1300
            sharedVariable = 1400

        expect:
            printVariables()
            /*
            initializedVariable: 1100
            globalVariable: 1200
            STATIC_VARIABLE: 1300
            sharedVariable: 1400
             */
    }

    void 'print values again'() {
        expect:
            printVariables()
            /*
            initializedVariable: 100
            globalVariable: 200
            STATIC_VARIABLE: 1300
            sharedVariable: 1400
             */
    }

    private void printVariables() {
        println "initializedVariable: $initializedVariable"
        println "globalVariable: $globalVariable"
        println "STATIC_VARIABLE: $STATIC_VARIABLE"
        println "sharedVariable: $sharedVariable\n"
    }
}

Удивительная вещь для меня заключается в том, что как переменная в методе класса setup() AS WELL, так и глобальная, instanced переменная get reset для каждого теста (по-видимому, потому, что класс повторно создается для каждого тестового примера), Между тем переменная static и @Shared работает должным образом. В результате последние два могут быть доступны в предложениях where, которые выполняются перед некоторыми из других, которые перечислены ранее в каждом тестовом случае.