Spock测试:调用过多

问题描述 投票:0回答:1

我编写了将事件从一个队列手动重排到另一个队列的服务。

public class ReQueueService {
  private final RabbitTemplate rabbitTemplate;

  public void retry() {
    InfoLog infoLog;
    while (rabbitTemplate != null && 
      (infoLog = (InfoLog) rabbitTemplate.receiveAndConvert(EVENT_WAITING_FOR_REQUEUE)) != null
    ) {
      rabbitTemplate.convertAndSend(SOME_QUEUE, infoLog.getSomeEvent());
    }
  }
}

我面临的问题正在得到:

Too many invocations for:

1 * rabbitTemplate.convertAndSend(SOME_QUEUE, _ as SomeEvent) >> {
      arguments ->
        assert infoLog.getSomeEvent() == arguments[1]
    }   (2 invocations)

Matching invocations (ordered by last occurrence):

2 * rabbitTemplate.convertAndSend(SOME_QUEUE, ...

我的测试代码如下:

class ReQueueServiceTest extends Specification {
  def "should resend single event to some queue" () {
    given:
    InfoLog infoLog = Fixtures.createInfoLog()
    def rabbitTemplate = Mock(RabbitTemplate){
      receiveAndConvert(EVENT_WAITING_FOR_REQUEUE) >> { infoLog }
    }
    ReQueueService reSyncService = new ReQueueService(rabbitTemplate)

    when:
    reSyncService.retry()

    then:
    1 * rabbitTemplate.convertAndSend(SOME_QUEUE, _ as SomeEvent) >> {
      arguments ->
        assert infoLog.getSomeEvent() == arguments[1]
    }
  }
}

问题是,如果仅保留一个事件,为什么我有两个调用?

编辑:

与回购链接,例如:https://gitlab.com/bartekwichowski/spock-too-many

spock
1个回答
0
投票

感谢回购链接。一旦我可以运行测试并实时检查行为,就很容易找出问题所在。首先,我将对您实际要测试的内容进行有根据的猜测:

  1. 模拟的receiveAndConvert方法应在首先被调用时返回str,然后在再次被调用时返回null
  2. 随后您要验证while循环是否恰好运行了1次迭代,即convertAndSend的调用正好是您期望的参数。

可以通过以下方式实现

  1. receiveAndConvert("FOO") >>> [str, null]
  2. 1 * rabbitTemplate.convertAndSend("BAR", str)(无需在存根方法中使用丑陋的断言,就已经根据您的参数约束对参数进行了验证)

如果我为更漂亮的变量名和较少的冗长性而重构您的规范,看起来像这样:

package com.example.demo

import org.springframework.amqp.rabbit.core.RabbitTemplate
import spock.lang.Specification

class ReSyncServiceTest extends Specification {
  def "should resend single event to resource sync queue" () {
    given:
    def message = "someValue"
    def rabbitTemplate = Mock(RabbitTemplate){
      receiveAndConvert("FOO") >>> [message, null]
    }
    def reSyncService = new ReSyncService(rabbitTemplate)

    when:
    reSyncService.retry()

    then:
    1 * rabbitTemplate.convertAndSend("BAR", message)
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.