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

斯波克-如何处理重复的交互

谭铭
2023-03-14

如http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_explicit_interaction_blocks中所述,我在then:块中使用interaction{},如下所示:

Java代码:

// legacy code (still running on EJB 1.0 framework, and no dependency injection involved)
// can't alter java code base

public voidGetData() {
  DataService ds = new DataService();
  ds = ds.findByOffset(5);
  Long len = ds.getOffset() // happy path scenario; missing a null check
  // other code
}

// other varieties of same code:
public voidGetData2() {
  ItemEJB tmpItem = new ItemEJB();
  ItemEJB item = tmpItem.findByOffset(5);
  if(null != item) {
    Long len = item.getOffset();
    // other code
  }
}

public voidGetData3() {
  ItemEJB item = new ItemEJB().findByOffset(5);
  if(null != item) {
    Long len = item.getOffset();
    // other code
  }
}

斯波克试验:

def "test scene1"() {
  given: "a task"
  // other code ommitted
  DataService mockObj = Mock(DataService)

  when: "take action"
  // code omitted

  then: "action response"
  interaction {
    verifyNoDataScenario()    // How to add verifyErrorScenario() interaction to the list?
  }
}

private verifyDataScenario() {
  1 * mockObj.findByOffset(5) >> mockObj // the findByOffset() returns an object, so mapped to same mock instance
  1 * mockObj.getOffset() >> 200
}

private verifyErrorScenario() {
  1 * mockObj.findByOffset(5) >> null // the findByOffset() returns null
  0 * mockObj.getOffset() >> 200  // this won't be executed, and should ie expected to throw NPE
}
    null

共有1个答案

楚元章
2023-03-14

你的应用程序代码看起来很奇怪。您的遗留应用程序中的编程风格真的那么糟糕吗?首先,使用无参数构造函数创建DataService对象,在下一步中通过调用该实例上的方法来覆盖该对象,该方法再次返回DataService对象。什么样的程序员会创建那样的代码?或者您只是编造了一些与实际应用程序没有太多共同之处的伪代码?请解释一下。

至于您的测试代码,它也没有意义,因为您将DataService Mockobj实例化为特性方法(测试方法)中的局部变量,这意味着在帮助器方法中Mockobj无法访问。因此,要么需要将对象作为参数传递给帮助器方法,要么需要将其作为测试类中的字段。

最后,但并非最不重要的一点是,您的本地模拟对象永远不会注入到被测试的类中,因为正如我在第一段中所说,getdata()中的dataservice对象也是一个局部变量。除非您的应用程序代码是完全伪造的,否则无法插入模拟,因为getData()没有任何方法参数,并且DataService对象不是可以通过setter方法或构造函数设置的字段。因此,您可以根据需要创建任意多个模拟,但应用程序永远不会知道它们。因此,您的stubbingfindbyoffset(长偏移量)(为什么不显示该方法的代码呢?)没有任何影响。

底线:请提供一个反映实际代码结构的例子,包括应用程序和测试代码。不幸的是,您提供的代码片段没有任何意义。我想帮忙,但就像这样,我做不到。

更新:

在我的注释中,我提到通过添加构造函数、setter方法或带有附加参数的重载getdata方法来重构遗留代码的可测试性。下面是我的意思的一个例子:

虚拟帮助程序类:

package de.scrum_master.stackoverflow.q58470315;

public class DataService {
  private long offset;

  public DataService(long offset) {
    this.offset = offset;
  }

  public DataService() {}

  public DataService findByOffset(long offset) {
    return new DataService(offset);
  }

  public long getOffset() {
    return offset;
  }

  @Override
  public String toString() {
    return "DataService{" +
      "offset=" + offset +
      '}';
  }
}
package de.scrum_master.stackoverflow.q58470315;

public class ToBeTestedWithInteractions {
  private DataService ds;

  public void setDataService(DataService ds) {
    this.ds = ds;
  }

  // legacy code; can't alter
  public void getData() {
    if (ds == null)
      ds = new DataService();
    ds = ds.findByOffset(5);
    Long len = ds.getOffset();
  }
}
package de.scrum_master.stackoverflow.q58470315

import spock.lang.Specification

class RepeatedInteractionsTest extends Specification {
  def "test scene1"() {
    given: "subject under test with injected mock"
    ToBeTestedWithInteractions subjectUnderTest = new ToBeTestedWithInteractions()
    DataService dataService = Mock()
    subjectUnderTest.dataService = dataService

    when: "getting data"
    subjectUnderTest.getData()

    then: "no error, normal return values"
    noExceptionThrown()
    1 * dataService.findByOffset(5) >> dataService
    1 * dataService.getOffset() >> 200

    when: "getting data"
    subjectUnderTest.getData()

    then: "NPE, only first method called"
    thrown NullPointerException
    1 * dataService.findByOffset(5) >> null
    0 * dataService.getOffset()
  }
}
 类似资料:
  • 我在spock和groovy的初始阶段,我试图测试一个简单的Spring启动应用程序,并获得 下面是我的java和groovy代码以及异常详细信息 TestController.java TestControllerSpec。棒极了 我确信我的代码遗漏了什么

  • 我有一个关于SPOCK+Drools测试的问题。事情是这样的, 我正在部署的webapp W/O中运行测试(如果这有任何意义的话:))。我将jar添加到类路径中(而不是WEB-INF/libs),现在运行良好。

  • 我想探听Spring Bean的方法调用。我检查了Docs-Spock只能通过构造函数创建间谍。Spock可以用间谍包裹已经存在的物体吗?

  • 我在spock框架测试方面是非常新的,我没有找到任何可以找到所需信息的例子。因此,我认为最好的方法是向一个例子展示我需要拥有的东西。 > 例如。斯波克的测试类: 将数据作为域类: 现在我有了测试,并且想模拟唯一的方法。这意味着每次调用时,都需要有msg成功的对象数据,但是方法中的所有其他方法都应该正常调用。 很可以理解吗?问题是如何将服务类注入/模拟到spock测试类中?

  • 我正在尝试以下场景: 正在申请中。属性设置为max.poll。记录是50 正在申请中。属性设置enable auto commit=false,并将确认模式设置为手动 在我的方法中添加了@KafkaListener,但不提交任何消息,只需阅读、记录,但不进行确认 事实上,在我的Kafka主题中,我有500条消息要消费,所以我期待以下行为: Spring Kafka民意测验()50条消息(偏移0到5

  • 是否有人使用RecyclerView找到了将onClickListener设置为RecyclerView中的项的方法? 请帮帮我...我是初学者:)