当前位置: 首页 > 知识库问答 >
问题:

Spock测试框架中Mock/Stub/Spy的区别

轩辕涵亮
2023-03-14

我不明白Spock测试中Mock、Stub和Spy之间的区别,我一直在网上看的教程也没有详细解释它们。

共有1个答案

袁宜民
2023-03-14

注意:我将在接下来的段落中过于简化,甚至可能略微篡改。有关更多详细信息,请参见马丁·福勒的网站。

模拟类是一个替代真实类的虚拟类,为每个方法调用返回类似null或0的内容。如果您需要一个复杂类的虚拟实例,那么您可以使用mock。否则,复杂类将使用外部资源,如网络连接、文件或数据库,或者可能使用数十个其他对象。mocks的优点是可以将测试中的类与系统的其余部分隔离开来。

存根也是一个虚拟类,为测试中的某些请求提供一些更具体的、准备好的或预先记录的、重播的结果。你可以说存根是一个花哨的嘲弄。在Spock中,您经常会读到存根方法。

    null
package de.scrum_master.stackoverflow

import org.spockframework.mock.TooFewInvocationsError
import org.spockframework.runtime.InvalidSpecException
import spock.lang.FailsWith
import spock.lang.Specification

class MockStubSpyTest extends Specification {

  static class Publisher {
    List<Subscriber> subscribers = new ArrayList<>()

    void addSubscriber(Subscriber subscriber) {
      subscribers.add(subscriber)
    }

    void send(String message) {
      for (Subscriber subscriber : subscribers)
        subscriber.receive(message);
    }
  }

  static interface Subscriber {
    String receive(String message)
  }

  static class MySubscriber implements Subscriber {
    @Override
    String receive(String message) {
      if (message ==~ /[A-Za-z ]+/)
        return "ok"
      return "uh-oh"
    }
  }

  Subscriber realSubscriber1 = new MySubscriber()
  Subscriber realSubscriber2 = new MySubscriber()
  Publisher publisher = new Publisher(subscribers: [realSubscriber1, realSubscriber2])

  def "Real objects can be tested normally"() {
    expect:
    realSubscriber1.receive("Hello subscribers") == "ok"
    realSubscriber1.receive("Anyone there?") == "uh-oh"
  }

  @FailsWith(TooFewInvocationsError)
  def "Real objects cannot have interactions"() {
    when:
    publisher.send("Hello subscribers")
    publisher.send("Anyone there?")

    then:
    2 * realSubscriber1.receive(_)
  }

  def "Stubs can simulate behaviour"() {
    given:
    def stubSubscriber = Stub(Subscriber) {
      receive(_) >>> ["hey", "ho"]
    }

    expect:
    stubSubscriber.receive("Hello subscribers") == "hey"
    stubSubscriber.receive("Anyone there?") == "ho"
    stubSubscriber.receive("What else?") == "ho"
  }

  @FailsWith(InvalidSpecException)
  def "Stubs cannot have interactions"() {
    given: "stubbed subscriber registered with publisher"
    def stubSubscriber = Stub(Subscriber) {
      receive(_) >> "hey"
    }
    publisher.addSubscriber(stubSubscriber)

    when:
    publisher.send("Hello subscribers")
    publisher.send("Anyone there?")

    then:
    2 * stubSubscriber.receive(_)
  }

  def "Mocks can simulate behaviour and have interactions"() {
    given:
    def mockSubscriber = Mock(Subscriber) {
      3 * receive(_) >>> ["hey", "ho"]
    }
    publisher.addSubscriber(mockSubscriber)

    when:
    publisher.send("Hello subscribers")
    publisher.send("Anyone there?")

    then: "check interactions"
    1 * mockSubscriber.receive("Hello subscribers")
    1 * mockSubscriber.receive("Anyone there?")

    and: "check behaviour exactly 3 times"
    mockSubscriber.receive("foo") == "hey"
    mockSubscriber.receive("bar") == "ho"
    mockSubscriber.receive("zot") == "ho"
  }

  def "Spies can have interactions"() {
    given:
    def spySubscriber = Spy(MySubscriber)
    publisher.addSubscriber(spySubscriber)

    when:
    publisher.send("Hello subscribers")
    publisher.send("Anyone there?")

    then: "check interactions"
    1 * spySubscriber.receive("Hello subscribers")
    1 * spySubscriber.receive("Anyone there?")

    and: "check behaviour for real object (a spy is not a mock!)"
    spySubscriber.receive("Hello subscribers") == "ok"
    spySubscriber.receive("Anyone there?") == "uh-oh"
  }

  def "Spies can modify behaviour and have interactions"() {
    given:
    def spyPublisher = Spy(Publisher) {
      send(_) >> { String message -> callRealMethodWithArgs("#" + message) }
    }
    def mockSubscriber = Mock(MySubscriber)
    spyPublisher.addSubscriber(mockSubscriber)

    when:
    spyPublisher.send("Hello subscribers")
    spyPublisher.send("Anyone there?")

    then: "check interactions"
    1 * mockSubscriber.receive("#Hello subscribers")
    1 * mockSubscriber.receive("#Anyone there?")
  }
}
 类似资料:
  • 我的测试代码: 唯一注册的是对PopulateEdgeInfo的调用。有什么明显的我做错了吗?也试图用模拟代替间谍,但没有用。

  • 本文向大家介绍Mock 与 Stub 有什么区别?相关面试题,主要包含被问及Mock 与 Stub 有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 Stub 一个有助于运行测试的虚拟对象。 在某些可以硬编码的条件下提供固定的行为。 从未测试stub的所有其他行为。 例如,对于空栈,你可以创建一个对于 empty() 方法只返回 true 的 stub。因此这并不关心栈中是否存在元素。 模拟

  • 当类是间谍时,如何可能在Spock测试中获得日志消息?

  • 我们实际上使用了JUnit和FakeSftpServerRule来测试我们定制的SFTP客户端。效果很好。 最后,我们希望摆脱junit,转而使用spock框架,因为我们试图迁移到groovy。 你们知道FakeSftpServerRule的等价物吗?或者,你们知道把junit规则“转换”成spock规则等价物的方法吗? 非常感谢。