没有太多可补充的,整个问题都在标题中。
考虑一个Spock规范中使用的Foo类的这两个实例。
@Shared Foo foo1 = new Foo()
static Foo foo2 = new Foo()
总的来说,我知道@Shared
注解背后的想法,但我认为更好的做法是使用语言特性,比如这种情况下应该使用static
字段。
是否有特定情况应该优先考虑其中之一,还是只是口味问题?
没有太多可补充的,整个问题都在标题中。
考虑一个Spock规范中使用的Foo类的这两个实例。
@Shared Foo foo1 = new Foo()
static Foo foo2 = new Foo()
总的来说,我知道@Shared
注解背后的想法,但我认为更好的做法是使用语言特性,比如这种情况下应该使用static
字段。
是否有特定情况应该优先考虑其中之一,还是只是口味问题?
Spock强调表达性和清晰度。
Static是Java中的一个关键字,仅显示类的内部(即该字段对所有实例都相同)。
@Shared是Spock的一个特性,它告诉读者这个变量对于所有特性方法都是相同的。它是针对单元测试的指令,使单元测试对读者更加清晰。
对于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
}
两个单元测试在技术上执行完全相同的操作。但第二个清楚地显示了意图。 when:和then:标签实际上并不对代码做任何事情,只是澄清其意图。
因此,总结一下,@Shared 使测试更易读。(另请参见@Issue、@Title等,它们存在的目的相同)
与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导致的。
作为一种更详尽的方法,这里提供了一个带有输出结果的样例测试:
@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
子句中进行访问,在每个测试用例中列出的一些其他子句之前运行。@Test
用例实例化,这对于JUnit来说也是一样的。您能详细解释一下最后一句话吗?我不太明白。 - Valya静态字段只应用于常量。否则,共享字段更可取,因为它们在共享方面的语义更加明确定义。
@Shared
更能表达你的意图。 - tim_yates