Spock模拟验证返回0调用 [英] Spock mock verify returns 0 invocations

查看:166
本文介绍了Spock模拟验证返回0调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用包含Camel Processor类的Spring Boot Java服务,

Im working on a Spring Boot java service that contains a Camel Processor class as follows:

public class MyProc implements Processor {

    @Autowired
    private LogService logService;

    public void process(Exchange e) {
            // exchange object processing
            logService.update(e)
        }   
}

我有以下Spock测试:

And I have the following Spock test:

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中命中了该语句,并且突出显示了(在Eclipse中)logService对象状态为名为$ spock_sharedField_logService类型的LogService类型的模拟",因此看起来该模拟已成功注入到MyProc实例中

When I run this, I get a failure, stating too few invocations for 1 * logService.update(_) (0 invocations). I tried debugging the code, and in MyProc, the statement is hit, and the logService object when highlighted(in Eclipse) states 'Mock for type LogService named $spock_sharedField_logService', so it looks like the mock has been successfully injected into the MyProc instance.

我是Spock和Groovy的新手,所以我可能会缺少一些东西,但是测试不应该通过吗?运行测试时将调用模拟方法,因此我不明白为什么测试会报告完全没有调用模拟方法.我是否在MyProc实例上初始化模拟/设置模拟/错误地设置交互?我错过了一些Groovy功能或警告吗?据我了解,Spock模拟会在调用时从方法中返回默认值,这很好,我只想检查此特定方法是否已作为带有有效交换对象的proc.process的一部分被调用

Im new to Spock and to Groovy so I may be missing something, but shouldn't thetest pass? The mocks method is being invoked when the test is ran, so I don't understand why the test is reporting back that the mocks method has not been called at all. Am I initialising the mock/setting the mock on the MyProc instance/ setting the interactions incorrectly? Is there some Groovy feature or caveat that I've missed? From what I understand, Spock mocks will return a default value from a method when called, which is fine, I just want to check that this particular method has been called as part of proc.process with a valid exchange object

推荐答案

一个简单的答案就是不要将@Shared用于模拟/存根/间谍.

A simple answer would be don't use @Shared for mocks/stubs/spies.

@Shared def proc = new MyProcessor()

def test() {
    given:
    def log = Mock(LogService)
    proc.logService = log

    when:
    proc.process(new Object())

    then:
    1 * log.update(_)
}

现在说明: 运行规范时,Spock会为每个测试创建一个Specification实例,此外,它还会创建一个共享的Specification实例来跟踪共享字段.

Now the explanation: When you run your spec Spock creates a Specification instance for each test, plus, it creates a shared Specification instance to keep track of shared fields.

查看org.spockframework.runtime.BaseSpecRunner,您将看到两个字段:

Look into org.spockframework.runtime.BaseSpecRunner and you will see two fields:

protected Specification sharedInstance;
protected Specification currentInstance;

此外,有两个规范上下文:共享和当前.上下文保留实例,模拟上下文和模拟控制器.问题来了.当您宣布模拟共享时,它绑定到共享模拟控制器,但是当您拒绝交互("then:"块)时,Spock会将这些交互添加到当前的模拟控制器中.因此,当调用模拟方法(例如logService.update(e))时,Spock会检查是否允许与共享模拟控制器进行此交互,因为您将模拟声明为共享但未在其中找到任何东西,因为您已将交互置于当前控制器中.

Moreover, there are two specification contexts: shared and current. The context keeps the instance, mock context and a mock controller. Here goes the problem. As you declare your mock as shared it is bind to the shared mock controller, but when you declair interactions ('then:' block) Spock adds these interactions to the current mock controller. So when the mock method is invoked (e.g. logService.update(e)) Spock checks if this interaction is allowed with the shared mock controller, as you declare the mock as shared but finds nothing there, because you put the interaction in the current controller.

请勿将模拟/存根/间谍用作@Shared字段.

这篇关于Spock模拟验证返回0调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆