Java Spock mock verify返回0个调用
我正在使用Spring Boot java服务,该服务包含一个驼峰处理器类,如下所示:Java Spock mock verify返回0个调用,java,unit-testing,spring-boot,apache-camel,spock,Java,Unit Testing,Spring Boot,Apache Camel,Spock,我正在使用Spring Boot java服务,该服务包含一个驼峰处理器类,如下所示: public class MyProc implements Processor { @Autowired private LogService logService; public void process(Exchange e) { // exchange object processing logService.update(e
public class MyProc implements Processor {
@Autowired
private LogService logService;
public void process(Exchange e) {
// exchange object processing
logService.update(e)
}
}
我有下面的斯波克测试:
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中)状态为“Mock for type logService named$spock\u sharedField\u logService”,因此看起来Mock已成功注入MyProc实例
我是斯波克和Groovy的新手,所以我可能遗漏了一些东西,但测试不应该通过吗?mocks方法在测试运行时被调用,所以我不明白为什么测试报告mocks方法根本没有被调用。我是否初始化模拟/在MyProc实例上设置模拟/设置交互不正确?是否有一些我错过的Groovy特性或警告?据我所知,Spock mocks在调用时将从一个方法返回一个默认值,这很好,我只想检查这个特定的方法是否作为proc.process的一部分使用了一个有效的exchange对象进行了调用
@Shared def proc = new MyProcessor()
def test() {
given:
def log = Mock(LogService)
proc.logService = log
when:
proc.process(new Object())
then:
1 * log.update(_)
}
现在解释一下:
运行spec时,Spock会为每个测试创建一个规范实例,另外,它还会创建一个共享规范实例来跟踪共享字段
查看org.spockframework.runtime.BaseSpecRunner,您将看到两个字段:
protected Specification sharedInstance;
protected Specification currentInstance;
此外,有两个规范上下文:共享和当前。上下文保留实例、模拟上下文和模拟控制器。问题来了。当您将模拟声明为共享时,它将绑定到共享模拟控制器,但当您声明交互('then:'block)时,Spock会将这些交互添加到当前模拟控制器。因此,当调用mock方法(例如logService.update(e))时,Spock会检查是否允许与共享mock控制器进行此交互,因为您将此交互放置在当前控制器中,因此您将该mock声明为共享,但在其中找不到任何内容
不要将mock/stubs/spies用作@Shared字段。一般来说,字段注入有问题——尽可能使用构造函数注入。如果删除
@Shared
,会发生什么?看起来您只实例化了一次mock(通常每个方法都会重置它),但每次都会重建上下文。这种不匹配可能会导致问题。删除shared并切换到void setup()vs setupSpec是有效的,谢谢。因此我认为每个feature方法都会获得自己的实例字段副本,这难道不意味着每个测试都有一个新版本的proc和logService吗?@shared
明确表示“不要为每个功能方法创建新副本”。或者至少是Spock Mock。仍然有一些边缘情况(例如Spring上下文注入)需要使用Mockito mocks.twitch