我正在运行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测试的正确语法是什么?
在命令中使用unit
和unit:
以及unit:spock
之间有什么区别?
(由于Spock附带Grails 2.5.0,它无论如何都会运行spocks测试。)
正确的语法是什么?为什么它会看到2个测试而不是1?
答案 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?
}
}
最后一个问题:这是一个横幅术语代码吗? (只是好奇)