代码之家  ›  专栏  ›  技术社区  ›  topr

什么时候Spock的@Shared注释应该优先于静态字段?

  •  32
  • topr  · 技术社区  · 9 年前

    没有什么可补充的,整个问题都在标题中。

    考虑一下Spock规范中使用的Foo类的这两个实例。

    @Shared Foo foo1 = new Foo()
    
    static Foo foo2 = new Foo()
    

    总的来说,我知道背后的想法 @Shared 注释,但我想最好使用语言特性,在本例中 static 领域

    有没有什么特定的情况下,一个人应该优先于另一个人,或者这是一个口味的问题?

    4 回复  |  直到 9 年前
        1
  •  28
  •   kazanaki    9 年前

    斯波克是关于 表现力 清晰 .

    静止的 是一个Java关键字,仅显示类的内部(该字段对于所有实例都相同)

    @共享 是一个Spock特性,它告诉读者这个变量对于所有特性方法都是相同的。这是一个专门用于单元测试的指令,使读者更清楚地了解单元测试。

    对于主要的斯波克街区来说也是如此。如果你仔细想想,他们并没有真正改变代码上的任何内容。

    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
    }
    

    两个单元测试在技术上做的完全相同。然而,第二个更清楚地表明了意图。这个 什么时候: 那么: 除了澄清代码的意图之外,标签实际上对代码没有任何作用。

    综上所述, @共享 使测试更具可读性。(另请参见 @问题 , @标题 它们存在的目的相同)

        2
  •  11
  •   Valya    8 年前

    与JUnit相反,您必须声明字段变量 静止的 并在中为其赋值

    @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
  •  3
  •   Igor luckyamit    4 年前

    作为一种更详尽的方法,这里有一个输出的示例测试:

    @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() 方法以及全局实例化变量在每次测试中都会被重置(大概是因为每个测试用例都会重新实例化类)。同时 static @Shared 可变工作。因此,后两者也可以在 where 子句,它们在每个测试用例之前列出的其他一些子句之前运行。

        4
  •  1
  •   jun zhou    6 年前

    静态字段只能用于常量。否则,共享字段更可取,因为它们与共享相关的语义定义更明确。