【问题标题】:Mocking does not work in parameterized test Spock模拟在参数化测试 Spock 中不起作用
【发布时间】:2020-09-22 16:32:49
【问题描述】:

所以我正在努力学习 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 列表转换为一个字符串的方法来测试类。 而且我有三个测试用例,只有第一个工作正常。

WeaponWriter#writeWeapon 只是遍历武器列表,并为每个武器调用Weapon#content,然后将它们组合成一个字符串。

从我看到的出于某种原因嘲笑weaponMocked.content() &gt;&gt; "BF Sword" 不会返回BF Sword,有人知道为什么吗?


当我不使用参数化测试时,一切正常。

【问题讨论】:

  • 请编辑您的问题,将其转换为MCVE。我看不到你在测试中的课程WeaponWeaponWriter,所以我不能说你的测试失败的原因。如果您想要答案,而不是纯粹的猜测,请改进问题。谢谢你。顺便说一句,@Shared 通常被过度使用并具有潜在危险,因为理想情况下测试不应该对彼此产生副作用。为什么你认为你需要它?

标签: unit-testing groovy spock


【解决方案1】:

好的,我想我已经发现了:正如我所说,您使用 @Shared 模拟,而不是为每个功能方法的每次迭代创建新模拟,可能是因为您想在 where: 块中使用它们。然后,即使共享变量应在声明期间直接初始化或从setupSpec() 方法初始化,您仍尝试从测试中为这些模拟存根方法。更糟糕的是,您试图为每次迭代重新初始化存根方法,这绝对是个坏主意。

假设我们有这些类在测试中(我使用的是 Groovy,也可以是类似的 Java 类):

package de.scrum_master.stackoverflow.q64013999

class Weapon {
  private String name

  Weapon(String name) {
    this.name = name
  }

  String content() {
    name
  }
}
package de.scrum_master.stackoverflow.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.stackoverflow.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.stackoverflow.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。谢谢你。这是你让我做你的工作,问一个正确的问题的免费机会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多