没有太多补充,整个问题都在标题中。
考虑Spock规范中使用的这两个Foo类实例。
@Shared Foo foo1 = new Foo()
static Foo foo2 = new Foo()
总的来说,我知道@Shared
注释背后的想法,但我认为使用语言功能会更好,在这种情况下会是static
字段。
是否有任何特定的案例,其中一个人应该优先于另一个,或者它是一个品味问题?
答案 0 :(得分:13)
Spock完全是关于表现力和清晰度。
静态是一个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 等,它们存在的目的相同)
答案 1 :(得分:9)
与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。
答案 2 :(得分:1)
作为一种更详尽的方法,这是一个带有输出的样本测试:
@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,因为全局的实例变量在每次测试时都会重置(可能是因为每个测试用例都重新实例化了类)。同时,static
和@Shared
变量按预期工作。因此,后两者也可以在where
子句中访问,这些子句在每个测试用例之前列出的其他一些子句之前运行。
答案 3 :(得分:0)
静态字段只能用于常量。否则,共享字段是更可取的,因为它们在共享方面的语义更加明确。