当前位置: 首页 > 知识库问答 >
问题:

Spock模拟验证返回0个调用

易阳朔
2023-03-14

我正在处理一个Spring Boot java服务,该服务包含一个Camel处理器类,如下所示:

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_sharedfield_logservice”,因此看起来mock已经成功地注入到MyProc实例中。

我对Spock和Groovy是新来的,所以我可能错过了什么,但这难道不应该通过吗?mocks方法是在测试运行时调用的,所以我不明白为什么测试会报告根本没有调用mocks方法。我是否在MyProc实例上初始化了模拟/设置了模拟/设置了交互错误?我是否遗漏了Groovy的某些特性或注意事项?据我所知,Spock mocks在调用方法时将返回一个默认值,这很好,我只是想检查这个特定的方法是否作为proc.process的一部分被调用,并使用有效的exchange对象

共有1个答案

施旭东
2023-03-14

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

@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为每个测试创建一个规范实例,另外,它还创建一个共享规范实例来跟踪共享字段。

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

protected Specification sharedInstance;
protected Specification currentInstance;

此外,还有两个规范上下文:shared和Current。上下文保存实例、模拟上下文和模拟控制器。问题来了。当您将模拟声明为shared时,它绑定到shared模拟控制器,但是当您声明interactions('then:'block)时,Spock将这些交互添加到当前模拟控制器中。因此,当调用mock方法(例如logservice.update(e))时,Spock检查是否允许与共享的mock控制器进行这种交互,因为您将mock声明为共享的,但在那里没有发现任何东西,因为您将交互放在了当前控制器中。

不要使用mock/stubs/spies作为@shared字段。

 类似资料:
  • 我在这件事上纠结了一段时间。是否可以模拟新URL(URL)。openStream()返回一个文件。广州?我正在使用斯波克来尝试这样做。 测试类 或者我最好编写一个私有方法来返回流?

  • 我正在尝试测试,只有在调用case的情况下,否则不会调用该方法。 但这会调用我的,并在内抛出空指针。因为我的行为不会调用,所以我如何在不调用的情况下测试它。

  • 如何测试是否调用了具有特定动态值的mocked logService方法? 也许我能抓住人格? 我不想注入UUID提供程序只是为了生成UUID并在测试中模拟它。但是我可以模拟/存根个人存储库(它是由Spring注入的)。

  • 我正在学习使用Spock进行单元测试,遇到了一个我似乎无法理解的问题: 注意:这个例子非常简化,但它得到了我想要实现的概念。 在正常操作中,调用会阻塞,直到建立到的连接。 我希望能够测试返回的上的交互。我可以通过以下方式与Spock一起做到这一点: 乍一看,这工作得很好,只是对的每次调用都将返回经过嘲弄的。由于此调用(有意地)被调用的次数不确定(因为我想接受不确定数量的入站连接),所以mock上的

  • 给定一个类Foo 为什么我用Spock来嘲笑Foo 调用总是返回false? 不确定这是否有区别,但测试是在Groovy/Spock中进行的,而Foo是在Java8中进行的。

  • 我试图为一个类编写一个单元测试,这个类使用带有库中的的Google vision API。问题是,由于某种原因,我的模拟仍然调用真正的方法,然后抛出一个NPE,这破坏了我的测试。我以前从未在模拟上见过这种行为,我想知道我是不是做错了什么,是不是Spock/Groovy中有bug,还是与Google lib有关?