模拟在参数化测试 Spock 中不起作用
Mocking does not work in parameterized test Spock
所以我正在努力学习 Spock 并且我正在努力创建测试。
private WeaponWriter writer;
@Shared
def emptyObject = Mock(Weapon)
@Shared
def weaponMocked = Mock(Weapon)
def: "should flatten object"(){
given:
emptyObject.content() >> ""
weaponMocked.content() >> "BF Sword"
List<Weapon> weaponList = Arrays.asList(weapon1, weapon2)
writer = new WeaponWriter(weaponList)
when:
def text = writer.writeWeapon()
then:
text == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked| emptyObject | "Headline" + "BF Sword"
weaponMocked| weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
如您所见,我想用将 Weapon
的列表转换为一个字符串的方法来测试 class。
我有三个测试用例,只有第一个可以正常工作。
WeaponWriter#writeWeapon
只是遍历武器列表,并为每个武器调用 Weapon#content
,然后将它们组合成一个字符串。
据我所知,出于某种原因,对 weaponMocked.content() >> "BF Sword"
的嘲笑不会 return BF Sword,有人知道为什么吗?
当我不使用参数化测试时,一切正常。
好吧,我想我已经发现了:正如我所说,您使用 @Shared
模拟而不是为每个特征方法的每次迭代创建新模拟,可能是因为您想从 where:
块。然后你试图从你的测试中为那些模拟存根方法,即使共享变量应该在声明期间直接初始化或从 setupSpec()
方法初始化。更糟糕的是,您试图 re-initialise 每次迭代的存根方法,这绝对是个坏主意。
让我们假设我们有这些 类 正在测试中(我正在使用 Groovy,也可以类似 Java 类):
package de.scrum_master.Whosebug.q64013999
class Weapon {
private String name
Weapon(String name) {
this.name = name
}
String content() {
name
}
}
package de.scrum_master.Whosebug.q64013999
class WeaponWriter {
private List<Weapon> weaponList
WeaponWriter(List<Weapon> weaponList) {
this.weaponList = weaponList
}
String writeWeapon() {
"Headline" + weaponList*.content().join("")
}
}
所以现在你至少有两个选择:
1.在模拟创建期间直接初始化存根:
package de.scrum_master.Whosebug.q64013999
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class WeaponWriterTest extends Specification {
private WeaponWriter writer
@Shared
def emptyObject = Mock(Weapon) {
content() >> ""
}
@Shared
def weaponMocked = Mock(Weapon) {
content() >> "BF Sword"
}
@Unroll
def "flatten weapon list into '#expectedText'"() {
given:
writer = new WeaponWriter([weapon1, weapon2])
expect:
writer.writeWeapon() == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked | emptyObject | "Headline" + "BF Sword"
weaponMocked | weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
}
2。初始化 setupSpec()
:
中的存根
package de.scrum_master.Whosebug.q64013999
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class WeaponWriterTest extends Specification {
private WeaponWriter writer
@Shared
def emptyObject = Mock(Weapon)
@Shared
def weaponMocked = Mock(Weapon)
def setupSpec() {
emptyObject.content() >> ""
weaponMocked.content() >> "BF Sword"
}
@Unroll
def "flatten weapon list into '#expectedText'"() {
given:
writer = new WeaponWriter([weapon1, weapon2])
expect:
writer.writeWeapon() == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked | emptyObject | "Headline" + "BF Sword"
weaponMocked | weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
}
拜托,下次请自己提供一个MCVE。谢谢你。这是我做你的工作的免费机会,问一个适当的问题。
所以我正在努力学习 Spock 并且我正在努力创建测试。
private WeaponWriter writer;
@Shared
def emptyObject = Mock(Weapon)
@Shared
def weaponMocked = Mock(Weapon)
def: "should flatten object"(){
given:
emptyObject.content() >> ""
weaponMocked.content() >> "BF Sword"
List<Weapon> weaponList = Arrays.asList(weapon1, weapon2)
writer = new WeaponWriter(weaponList)
when:
def text = writer.writeWeapon()
then:
text == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked| emptyObject | "Headline" + "BF Sword"
weaponMocked| weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
如您所见,我想用将 Weapon
的列表转换为一个字符串的方法来测试 class。
我有三个测试用例,只有第一个可以正常工作。
WeaponWriter#writeWeapon
只是遍历武器列表,并为每个武器调用 Weapon#content
,然后将它们组合成一个字符串。
据我所知,出于某种原因,对 weaponMocked.content() >> "BF Sword"
的嘲笑不会 return BF Sword,有人知道为什么吗?
当我不使用参数化测试时,一切正常。
好吧,我想我已经发现了:正如我所说,您使用 @Shared
模拟而不是为每个特征方法的每次迭代创建新模拟,可能是因为您想从 where:
块。然后你试图从你的测试中为那些模拟存根方法,即使共享变量应该在声明期间直接初始化或从 setupSpec()
方法初始化。更糟糕的是,您试图 re-initialise 每次迭代的存根方法,这绝对是个坏主意。
让我们假设我们有这些 类 正在测试中(我正在使用 Groovy,也可以类似 Java 类):
package de.scrum_master.Whosebug.q64013999
class Weapon {
private String name
Weapon(String name) {
this.name = name
}
String content() {
name
}
}
package de.scrum_master.Whosebug.q64013999
class WeaponWriter {
private List<Weapon> weaponList
WeaponWriter(List<Weapon> weaponList) {
this.weaponList = weaponList
}
String writeWeapon() {
"Headline" + weaponList*.content().join("")
}
}
所以现在你至少有两个选择:
1.在模拟创建期间直接初始化存根:
package de.scrum_master.Whosebug.q64013999
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class WeaponWriterTest extends Specification {
private WeaponWriter writer
@Shared
def emptyObject = Mock(Weapon) {
content() >> ""
}
@Shared
def weaponMocked = Mock(Weapon) {
content() >> "BF Sword"
}
@Unroll
def "flatten weapon list into '#expectedText'"() {
given:
writer = new WeaponWriter([weapon1, weapon2])
expect:
writer.writeWeapon() == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked | emptyObject | "Headline" + "BF Sword"
weaponMocked | weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
}
2。初始化 setupSpec()
:
package de.scrum_master.Whosebug.q64013999
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class WeaponWriterTest extends Specification {
private WeaponWriter writer
@Shared
def emptyObject = Mock(Weapon)
@Shared
def weaponMocked = Mock(Weapon)
def setupSpec() {
emptyObject.content() >> ""
weaponMocked.content() >> "BF Sword"
}
@Unroll
def "flatten weapon list into '#expectedText'"() {
given:
writer = new WeaponWriter([weapon1, weapon2])
expect:
writer.writeWeapon() == expectedText
where:
weapon1 | weapon2 | expectedText
emptyObject | emptyObject | "Headline"
weaponMocked | emptyObject | "Headline" + "BF Sword"
weaponMocked | weaponMocked | "Headline" + "BF Sword" + "BF Sword"
}
}
拜托,下次请自己提供一个MCVE。谢谢你。这是我做你的工作的免费机会,问一个适当的问题。