Over a million developers have joined DZone.

Grails Goodness: Testing Views and Templates

· DevOps Zone

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

Grails has great support for testing. We can unit test controllers, taglibs, services and much more. One of the things we can unit test are views and templates. Suppose we have a view or template with some (hopefully simple) logic (a view/template should not contain complex logic), for example an if-else statement to display some content conditionally. We can write a test in Grails to see if the logic is correctly implemented.

Let's first create a template in our Grails application:

%{-- File: /grails-app/views/sample/_header.gsp --}%
1.
<g:if test="${username}">
2.
<h1>Hi, ${username}</h1>
3.
</g:if>
4.
<g:else>
5.
<h1>Welcome</h1>
6.
</g:else>

The template checks if there is a username attribute and shows the value is there is, otherwise a simple "Welcome" message is shown.

We can test this with the following Spock specification. We use Spock for writing the test, because it makes writing tests so much easier and more fun! We must make sure we use the GroovyPageUnitTestMixin, because this will add a render() method to our tests. The render()method accepts a Map arguments where we can set the template or view and optionally the model with attributes.

// File: test/unit/com/mrhaki/grails/views/HeaderTemplateSpecification.groovy
01.
package com.mrhaki.grails.views
02.
 
03.
import grails.test.mixin.TestMixin
04.
import grails.test.mixin.web.GroovyPageUnitTestMixin
05.
import spock.lang.Specification
06.
 
07.
@TestMixin(GroovyPageUnitTestMixin)
08.
class HeaderTemplateSpecification extends Specification {
09.
 
10.
def "if username is set then show message Hi with username"() {
11.
expect: 'Template output must contain Hi, mrhaki'
12.
renderTemplateWithModel([username: 'mrhaki']).contains 'Hi, mrhaki'
13.
}
14.
 
15.
def "if username is not set then show message Welcome"() {
16.
expect: 'Template output must contain Welcome'
17.
renderTemplateWithModel().contains 'Welcome'
18.
}
19.
 
20.
private renderTemplateWithModel(model = [:]) {
21.
render(template: '/sample/header', model: model)
22.
}
23.
 
24.
}

Let's also write a simple Grails view GSP, which shows a list of items if items are set or otherwise show a message using the <g:message/>tag.

%{--File: grails-app/views/sample/items.gsp--}%
01.
<%@ page contentType="text/html;charset=UTF-8" %>
02.
<html>
03.
<head><title>Simple GSP page</title></head>
04.
<body>
05.
<g:if test="${items}">
06.
<ul>
07.
<g:each in="${items}" var="item">
08.
<li>${item}</li>
09.
</g:each>
10.
</ul>
11.
</g:if>
12.
<g:else>
13.
<g:message code="noitems"/>
14.
</g:else>
15.
</body>
16.
</html>

The following specification will check the output dependent on if there are elements in the model attribute items. Because we use GroovyPageUnitTestMixin we have access to a messageSource object where we can define values for keys that are used by the<g:message/> tag.

// File: test/unit/com/mrhaki/grails/views/ItemsViewSpecification.groovy
01.
package com.mrhaki.grails.views
02.
 
03.
import grails.test.mixin.TestMixin
04.
import grails.test.mixin.web.GroovyPageUnitTestMixin
05.
import spock.lang.Specification
06.
 
07.
@TestMixin(GroovyPageUnitTestMixin)
08.
class ItemsViewSpecification extends Specification {
09.
 
10.
def "if items are available then show items as list items"() {
11.
when:
12.
final String output = renderViewWithItems(['one'])
13.
 
14.
then:
15.
output.contains '<li>one</li>'
16.
}
17.
 
18.
def "if collection of items is empty then show message items are empty"() {
19.
given:
20.
messageSource.addMessage 'noitems', request.locale, 'NO_ITEMS'
21.
 
22.
when:
23.
final String output = renderViewWithItems()
24.
 
25.
then:
26.
output.contains 'NO_ITEMS'
27.
}
28.
 
29.
private renderViewWithItems(items = []) {
30.
render(view: '/sample/user', model: [items: items])
31.
}
32.
 
33.
}

Code written with Grails 2.2.1!

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today

Topics:

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}