Grails的Spock语法是什么?

时间:2015-08-06 15:13:55

标签: unit-testing grails spock

我正在运行Grails 2.5.0应用程序并进行此测试:

package moduleextractor

import grails.test.mixin.TestFor
import spock.lang.Specification

/**
 * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
 */
@TestFor(ExtractorController)
class ExtractorControllerSpec extends Specification {

    def moduleDataService
    def mockFile

    def setup() {
        moduleDataService = Mock(ModuleDataService)
        mockFile = Mock(File)
    }

    def cleanup() {
    }

    void "calls the moduleDataService"() {
        given: 'a term is passed'
            params.termCode = termCode
        when: 'the getModuleData action is called'
            controller.getModuleData()
        then: 'the service is called 1 time'
            1 * moduleDataService.getDataFile(termCode, 'json') >> mockFile
        where:
            termCode = "201415"
    }
}

如果我运行grails test-app unit:spock我就明白了:

| Tests PASSED - view reports in /home/foo/Projects/moduleExtractor/target/test-reports

我不明白为什么会看到2次测试。我没有在我的BuildConfig文件中包含spock,因为它已经包含在Grails 2.5.0中。此外测试不应该通过,因为我还没有服务。它为什么通过?

当我运行此grails test-app ExtractorController时,我得到另一个结果:

| Running 2 unit tests...
| Running 2 unit tests... 1 of 2
| Failure:  calls the moduleDataService(moduleextractor.ExtractorControllerSpec)
|  Too few invocations for:
1 * moduleDataService.getDataFile(termCode, 'json') >> mockFile   (0 invocations)
Unmatched invocations (ordered by similarity):
None
    at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:78)
    at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:76)
    at moduleextractor.ExtractorControllerSpec.calls the moduleDataService(ExtractorControllerSpec.groovy:27)
| Completed 1 unit test, 1 failed in 0m 3s
| Tests FAILED  - view reports in /home/foo/Projects/moduleExtractor/target/test-reports
| Error Forked Grails VM exited with error

如果我运行grails test-app unit:,我会:

| Running 4 unit tests...
| Running 4 unit tests... 1 of 4
| Failure:  calls the moduleDataService(moduleextractor.ExtractorControllerSpec)
|  Too few invocations for:
1 * moduleDataService.getDataFile(termCode, 'json') >> mockFile   (0 invocations)
Unmatched invocations (ordered by similarity):
None
    at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:78)
    at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:76)
    at moduleextractor.ExtractorControllerSpec.calls the moduleDataService(ExtractorControllerSpec.groovy:27)
| Completed 1 unit test, 1 failed in 0m 3s
| Tests FAILED  - view reports in /home/foo/Projects/moduleExtractor/target/test-reports
| Error Forked Grails VM exited with error

首先,有人可以告诉我运行spock测试的正确语法是什么?

在命令中使用unitunit:以及unit:spock之间有什么区别?

(由于Spock附带Grails 2.5.0,它无论如何都会运行spocks测试。)

正确的语法是什么?为什么它会看到2个测试而不是1?

2 个答案:

答案 0 :(得分:1)

不要关心测试次数。这对我来说从来都不是问题。您始终可以检查报告HTML文件,以确切了解运行的内容。

我总是用

运行我的测试
grails test-app

grails test-app ExtractorController

您获得的错误意味着您将测试编码为期望使用参数 null和' json' moduleDataService.getDataFile() em>当 controller.getModuleData()被调用时。但是, moduleDataService.getDataFile()从未被调用,因此测试失败。

Spock需要一些时间来适应。我建议您查看Grails文档中的示例并阅读Spock Framework Reference

答案 1 :(得分:1)

第一个问题:对于' grails test-app unit:spock',您是否看过结果以查看它所说的测试? CLI的测试计数可能是错误的,检查结果以查看实际运行的内容(如果没有测试实际运行,则没有失败)。

您的测试方法并非以测试'开头,也没有@Test注释,因此' void"调用moduleDataService"&# 39;并不被视为spock测试案例(我相信这就是原因)。

当你运行' grails test-app ExtractorController'时,你没有指定它必须是spock测试,所以grails测试找到并执行调用moduleDataService' 39;测试方法。

由于spock是事实上的测试框架,你可以使用: grails test-app -unit

第二个问题:

@TestFor创建你的控制器,但是如果你正在进行单元测试,那么通常的grails魔法就不会发生。您的控制器代码正在独立执行。如果你的ExtractorController通常注入了moduleDataService,你就必须要处理它。

我在grails 2.4.3中工作,这将是我对你的测试的解释(确实需要调整,因为我在这个例子中推断了很多):

import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.specification
import some.pkg.ModuleDataService // if necessary
import some.pkg.File // if necessary

@TestFor(ExtractorController)
@Mock([ModuleDataService, File])
class ExtractorControllerSpec extends Specification

    def "test callsModuleDataService once for a termCode"() {

        setup:
        def mockFile = mockFor(File)
        def mockService = mockFor(ModuleDataService, true) // loose mock
        // in this mockService, we expect getDataFile to be called
        // just once, with two parameters, and it'll return a mocked
        // file
        mockService.demand.getDataFile(1) { String termCode, String fmt ->
            return mockFile.createMock()
        }
        controller.moduleDataService = mockService.createMock()

        when:
        controller.params.termCode = "201415"
        controller.getModuleData()

        then:
        response.status == 200 // all good?
    }
}

最后一个问题:这是一个横幅术语代码吗? (只是好奇)