模拟在参数化测试 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。谢谢你。这是我做你的工作的免费机会,问一个适当的问题。