2015-08-06 3 views
0

У меня есть Grails 2.5.0 приложение работает, и этот тест:Каков правильный синтаксис Spock для Grails?

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 теста. Я не включил spock в свой файл BuildConfig, поскольку он уже включен в 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 

Прежде всего кто-то может сказать мне, что это правильный синтаксис для запуска пробные тесты?

В чем разница между наличием у команды unit и unit: и unit:spock?

(Так как Спок приходит с Grails 2.5.0, он будет работать spocks тесты в любом случае.)

Что такое правильный синтаксис и почему он видит 2 теста вместо 1?

ответ

1

Не заботьтесь о количестве тестов. Это никогда не было проблемой для меня. Вы всегда можете проверить HTML-файл отчета, чтобы увидеть, что именно произошло.

Я всегда запускать мои тесты либо

grails test-app 

или

grails test-app ExtractorController 

Ошибка вы получаете означает, что вы закодированы тест ожидать moduleDataService.getDataFile() получить колл с параметры null и 'json' когда контроллер.getModuleData() называется. Тем не менее, moduleDataService.getDataFile() никогда не вызывался, поэтому тест не удался. Скрытый текст. Я рекомендую посмотреть примеры в документации Grails и прочитать Spock Framework Reference.

1

Первый вопрос: для «градиентного тестового приложения: spock» вы просмотрели результаты, чтобы увидеть те тесты, которые, по его словам, прошли? Количество тестов в CLI может быть неправильным, проверьте результаты, чтобы увидеть, что на самом деле выполнялось (если тесты не выполнялись, тогда не было сбоев).

Ваш тестовый метод не начинается с «теста», и у него нет аннотации @Test, поэтому вызов «void» moduleDataService «» не рассматривается как тестовый пример спота (я считаю, что это причина).

Когда вы запускаете «grails test-app ExtractorController», вы не указываете, что это должен быть тест-спот, поэтому проверка Grails находит и выполняет метод «вызывает метод testDataService».

Поскольку Спока является де-факто тестирование рамки, вы можете просто использовать: Grails тест-приложение -Unit

Второй вопрос:

@TestFor создает свой контроллер, но если вы используете устройство тест, тогда обычной магии Грааля не происходит. Код контроллера выполняется изолированно. Если ваш ExtractorController обычно вводит moduleDataService, вам придется позаботиться об этом.

Я работаю в Грааль 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? 
    } 
} 

Последний вопрос: есть что код термина Баннера? (просто любопытно)

+0

сформируйте то, что я помню, что метод «void ...» пришел с тестом (я имею в виду, что он был сгенерирован, я просто переименовал его, разве аннотация не должна быть по умолчанию?). Кроме того, вы не использовали тестовую аннотацию в своем коде. Извините, но для меня это немного сбивает с толку. –

+0

Вы также говорите, что запускаете это: «grails test-app -unit» Я никогда раньше не видел этот синтаксис. Я, хотя двоеточие, ':' следует использовать. Однако я понимаю часть инъекции. Я должен определить свою службу в тесте! Спасибо, в любом случае! –

+0

Исправьте, нет аннотации @Test, но имя метода начинается с «теста», который является адекватным. Существует также несколько допустимых форматов для вызова модульных тестов. «grails test-app -unit» вызывает модульные тесты. 'grail test-app unit:' вызывает модульные тесты. – railsdog