简体   繁体   English

如何使用模拟使用 groovy-spock 编写参数化测试

[英]How to write parametrized tests with groovy-spock using mocks

I want to test this class using groovy with spock:我想使用带有 spock 的 groovy 来测试这个类:

class TaskRunner {
    private int threads
    private ExecutorService executorService
    private TaskFactory taskFactory

    // relevant constructor

    void update(Iterable<SomeData> dataToUpdate) {
        Iterable<List<SomeData>> partitions = partition(dataToUpdate, THREADS)
        partitions.each {
            executorService.execute(taskFactory.createTask(it))
        }
    }
}

I want to write test looking like this one:我想写一个看起来像这样的测试:

class TaskRunnerSpec extends specification {
    ExecutorService executorService = Mock(ExecutorService)
    TaskFactory taskFactory = Mock(TaskFactory)
    @Subject TaskRunner taskRunner = new TaskRunner(taskFactory, executorService)

    def "should run tasks partitioned by ${threads} value"(int threads) {
        given:
        taskRunner.threads = threads

        where:
        threads | _
              1 | _
              3 | _
              5 | _

        when:
        tasksRunner.update(someDataToUpdate())

        then:
        // how to test number of invocations on mocks?
    }
}

I see examples from documentation with only interacting testing with sections given , when , then and examples with data-driven tests, which have only two sections: expect and where .我看到文档中的示例仅与given部分given交互测试, whenthen和带有数据驱动测试的示例,其中只有两个部分: expectwhere

May I combine that two?我可以把这两者结合起来吗? Or how to achieve the same functionality?或者如何实现相同的功能?

Short answer yes they can be combined, but not in that order see the docs where must be the last block.简短的回答是,它们可以组合,但不能按该顺序查看文档where必须是最后一个块。 So given-when-then-where is perfectly fine.所以given-when-then-where是完全没问题的。 Correctly testing multi-threaded code is a lot harder, but since you mock the ExecutorService you don't have to worry about it.正确测试多线程代码要困难得多,但由于您模拟了ExecutorService您不必担心它。

Don't forget @Unroll and note that the templating is not using GString syntax.不要忘记@Unroll并注意模板没有使用 GString 语法。

class TaskRunnerSpec extends specification {
    ExecutorService executorService = Mock(ExecutorService)
    TaskFactory taskFactory = Mock(TaskFactory)
    @Subject TaskRunner taskRunner = new TaskRunner(taskFactory, executorService)

    @Unroll
    def "should run tasks partitioned by #threads value"(int threads) {
        given:
        taskRunner.threads = threads

        when:
        tasksRunner.update(someDataToUpdate())

        then:
        threads * taskFactory.createTask(_) >> new Task() // or whatever it creates
        threads * executorService.execute(_)

        where:
        threads | _
              1 | _
              3 | _
              5 | _

    }
}

BTW, the where block can be simplified to one line:顺便说一句, where块可以简化为一行:

where:
threads << [1, 3, 5]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM