3

Я пытаюсь проверить действие контроллера в тесте интеграции. Это простой сценарий, когда действие, которое я пытаюсь проверить, вызывает метод службы. Я пытаюсь переопределить этот метод с помощью метакласса, но похоже, что он не работает, т. Е. Реальный метод службы всегда получает вызов вместо того, который я переопределяю с помощью метакласса. Что я здесь делаю неправильно?Метод переопределения службы в тесте интеграции граблей

Вот метод контроллера:

class MyController { 
    MyService myService 

    def methodA() { 
    def u = myService.find(params.paramA) 
    render view: "profile", model: [viewed: u] 
    } 

Вот как я реализовать интеграционный тест:

class MyControllerTests extends GroovyTestCase { 

MyController controller 

void testMethodA() { 
    controller = new MyController() 

    // Mock the service 
    MyService mockService = new MyService() 
    mockService.getMetaClass().find = { String s -> 
     [] 
    } 

    controller = new MyController() 
    controller.myService = myService 

    controller.methodA() 
    } 

P.S. Я использую Grails 2.0.0 в STS 2.9.2

ответ

7

Прежде всего я рекомендую использовать Spock Framework, который действительно хороший кусок библиотеки тестирования, кроме того integrates with Grails pretty well. Ваш тест будет выглядеть так:

@TestFor(MyController) // TestFor is builtin Grails annotation 
class MyControllerSpec extends Specification { 

    // thanks to TestFor annotation you already have 'controller' variable in scope 

    MyService mockService = Mock(MyService) 

    // setup method is executed before each test method (known as feature method) 
    def setup() { 
     controller.myService = mockService 
    } 

    def 'short description of feature being tested'() { 
     given: 
     mockService.find(_) >> [] // this tells mock to return empty list for any parameter passed 

     when: 
     controller.methodA() 

     then: 
     // here goes boolean statements (asserts), example: 
     controller.response.text.contains 'Found no results' 
    } 
} 

Если вы предпочитаете остаться без Спока, для издеваться вам нужен самый простой способ будет использовать Groovy принуждением. Проверьте это:

MyService mockService = [find: { String s -> [] }] as MyService 

Это карта принуждении. В вашем случае, когда насмехается один метод, даже карта не нужна, поэтому вы можете написать ее проще.

MyService mockService = { String s -> [] } as MyService 

Это закрытия принуждение. Ну, указывая параметр не нужно, так как вы его не обрабатываете.

MyService mockService = { [] } as MyService 

Последнее утверждение в основном означает, чем любой метод, называемый на mockService выполнит указанное замыкание, поэтому пустой список будет возвращен в результате.

Проще, лучше, приветствия!

Кстати, при использовании Спока вы все еще можете использовать притворные издевки. Spock mocks (созданные с помощью метода Mock()) полезны для тестирования более сложных случаев, таких как, например, взаимодействия.

UPDATE: для тестирования интеграции вы должны расширить IntegrationSpec и не использовать @TestFor.

+1

topr, спасибо большое! Я закончил использовать технику принуждения, которую вы предложили, и все работает отлично. – Tomato

+1

Не вопрос для тестирования интеграции? Похоже, что код предназначен для модульного теста. –

1

Я предлагаю вам использовать Grails аннотацию насмешливый вашу службу, так как в следующем примере взяты из документации 10.1 Unit Testing:

@Mock([Book, Author, BookService]) 

Затем тестирует контроллер выглядит следующим образом:

void testSearch() { 
     def control = mockFor(SearchService) 
     control.demand.searchWeb { String q -> ['mock results'] } 
     control.demand.static.logResults { List results -> } 
     controller.searchService = control.createMock() 
     controller.search()  assert controller.response.text.contains "Found 1 results" 
} 
Смежные вопросы