我编写了将事件从一个队列手动重排到另一个队列的服务。
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]
}
}
}
问题是,如果仅保留一个事件,为什么我有两个调用?
编辑:
感谢回购链接。一旦我可以运行测试并实时检查行为,就很容易找出问题所在。首先,我将对您实际要测试的内容进行有根据的猜测:
receiveAndConvert
方法应在首先被调用时返回str
,然后在再次被调用时返回null
。while
循环是否恰好运行了1次迭代,即convertAndSend
的调用正好是您期望的参数。可以通过以下方式实现
receiveAndConvert("FOO") >>> [str, null]
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)
}
}