Статьи

Grails Goodness: модульное тестирование рендеринга шаблонов с контроллера

В предыдущем сообщении в блоге мы узнали, как мы можем протестировать шаблон или просмотреть его самостоятельно. Но что, если мы хотим провести модульное тестирование контроллера, который использует метод render() и шаблон с ключом template вместо представления? Обычно представление и модель хранятся в свойстве modelAndView ответа. Мы даже можем использовать ярлыки в нашем тестовом коде, такие как view и model чтобы проверить результат. Но вызов метода render() с ключом template просто выполнит шаблон (также в тестовом коде), и результат будет добавлен в ответ. С помощью свойства text ответа мы можем проверить результат.

В следующем примере контроллера мы используем шаблон header и передаем свойство модели username для визуализации вывода.

1
2
3
4
5
6
7
8
%{-- File: /grails-app/views/sample/_header.gsp --}%
  
<g:if test="${username}">
    <h1>Hi, ${username}</h1>
</g:if>
<g:else>
    <h1>Welcome</h1>
</g:else>
1
2
3
4
5
6
7
8
9
package com.mrhaki.grails.web
  
class SampleController {
  
    def index() {
        render template: 'header', model: [username: params.username]
    }
  
}

С помощью этой спецификации Спока мы тестируем действие index() :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.mrhaki.grails.web
  
import grails.test.mixin.TestFor
import spock.lang.Specification
  
@TestFor(SampleController)
class SampleControllerSpec extends Specification {
  
    def "index action renders template with given username"() {
        given:
        params.username = username
  
        when:
        controller.index()
  
        then:
        response.text.trim() == expectedOutput
  
        where:
        username || expectedOutput
        'mrhaki' || '<h1>Hi, mrhaki</h1>'
        null     || '<h1>Welcome</h1>'
    }
  
}

Предположим, что мы не хотим проверять вывод фактического шаблона, но мы только хотим проверить в нашем тестовом коде, что используется правильное имя шаблона и модель верна. Мы можем использовать свойства groovyPages или views в нашем тестовом коде, чтобы назначить ложную реализацию для шаблонов. groovyPages или views добавляются классом ControllerUnitTestMixin , что выполняется автоматически, если мы используем аннотацию @TestFor() . Свойства — это карты, где ключи — это местоположения шаблона, а значения — строки с имитационными реализациями для шаблона. Например, расположение шаблона для нашего шаблона header/sample/_header.gsp . Мы можем назначить фиктивную реализацию String с помощью следующего оператора: views['/sample/_header.gsp'] = 'mock implementation'

Мы можем переписать спецификацию Spock и теперь использовать макетные реализации для шаблона header . Мы даже можем использовать модель в нашей фиктивной реализации, чтобы проверить, правильно ли наша модель отправлена ​​в шаблон.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.mrhaki.grails.web
  
import grails.test.mixin.TestFor
import spock.lang.Specification
  
@TestFor(SampleController)
class SampleControllerSpec extends Specification {
  
    def "index action renders mock template with given username"() {
        given:
        // Mock implementation with escaped $ (\$), because otherwise
        // the String is interpreted by Groovy as GString.
        groovyPages['/sample/_header.gsp'] = "username=\${username ?: 'empty'}"
  
        // Or we can use views property:
        //views['/sample/_header.gsp'] = "username=\${username ?: 'empty'}"
  
        and:
        params.username = username
  
        when:
        controller.index()
  
        then:
        response.text.trim() == expectedOutput
  
        where:
        username || expectedOutput
        'mrhaki' || 'username=mrhaki'
        null     || 'username=empty'
    }
  
}