【发布时间】:2017-04-30 03:14:29
【问题描述】:
我正在开发一个包含 Camel 处理器类的 Spring Boot java 服务,如下所示:
public class MyProc implements Processor {
@Autowired
private LogService logService;
public void process(Exchange e) {
// exchange object processing
logService.update(e)
}
}
我有以下 Spock 测试:
class MyProcTest extends Specification {
@Shared def logService = Mock(LogService)
@Shared def proc = new MyProc()
def ctx = new DefaultCamelContext()
def exch = new DefaultExchange(ctx)
void setupSpec() {
proc.logService = logService
}
def "log is updated when valid exchange is processed"() {
given:
exch.getIn().setBody(//xml string set on body)
when:
proc.process(exch)
then:
1 * logService.update(_)
}
}
当我运行它时,我遇到了失败,说明 1 * logService.update(_) 的调用太少(0 调用)。我尝试调试代码,在 MyProc 中,该语句被命中,并且 logService 对象在突出显示时(在 Eclipse 中)状态为“模拟名为 $spock_sharedField_logService 的类型 LogService”,因此看起来模拟已成功注入 MyProc 实例.
我是 Spock 和 Groovy 的新手,所以我可能会遗漏一些东西,但测试不应该通过吗?运行测试时正在调用 mocks 方法,所以我不明白为什么测试报告根本没有调用 mocks 方法。我是否在 MyProc 实例上初始化模拟/设置模拟/错误地设置交互?是否有一些我错过的 Groovy 功能或警告?据我了解,Spock 模拟将在调用时从方法返回默认值,这很好,我只想检查这个特定方法是否已作为 proc.process 的一部分被调用,并具有有效的交换对象
【问题讨论】:
-
一般来说,字段注入存在问题——尽可能使用构造函数注入。
-
如果你放弃
@Shared会发生什么?看起来您正在实例化模拟 once (您通常按方法重置它)但每次都重建上下文。这种不匹配可能会导致问题。 -
放弃共享并切换到 void setup() vs setupSpec 工作,谢谢
-
另外我认为每个功能方法都会获得自己的实例字段副本,这不意味着每个测试都有新版本的 proc 和 logService 吗?
-
@Shared明确的意思是“不要为每个特征方法制作新的副本”。
标签: java unit-testing spring-boot apache-camel spock