import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(SimpleTagLib)
class SimpleTagLibSpec extends Specification {
void "test something"() {
}
}
15.1.2 Unit Testing Tag Libraries
Version: 3.2.7
15.1.2 Unit Testing Tag Libraries
The Basics
Tag libraries and GSP pages can be tested with the grails.test.mixin.web.GroovyPageUnitTestMixin
mixin. To use the mixin declare which tag library is under test with the TestFor
annotation:
Adding the TestFor
annotation to a TagLib class causes a new tagLib
field to be automatically created for the TagLib class under test.
The tagLib field can be used to test calling tags as function calls. The return value of a function call is either a StreamCharBuffer instance or
the object returned from the tag closure when returnObjectForTags feature is used.
Note that if you are testing invocation of a custom tag from a controller you can combine the ControllerUnitTestMixin
and the GroovyPageUnitTestMixin
using the Mock
annotation:
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
@TestFor(SimpleController)
@Mock(SimpleTagLib)
class SimpleControllerSpec extends Specification {
}
Testing Custom Tags
The core Grails tags don’t need to be enabled during testing, however custom tag libraries do. The GroovyPageUnitTestMixin
class provides a mockTagLib()
method that you can use to mock a custom tag library. For example consider the following tag library:
class SimpleTagLib {
static namespace = 's'
def hello = { attrs, body ->
out << "Hello ${attrs.name ?: 'World'}"
}
def bye = { attrs, body ->
out << "Bye ${attrs.author.name ?: 'World'}"
}
}
You can test this tag library by using TestFor
and supplying the name of the tag library:
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(SimpleTagLib)
class SimpleTagLibSpec extends Specification {
void "test hello tag"() {
expect:
applyTemplate('<s:hello />') == 'Hello World'
applyTemplate('<s:hello name="Fred" />') == 'Hello Fred'
applyTemplate('<s:bye author="${author}" />', [author: new Author(name: 'Fred')]) == 'Bye Fred'
}
void "test tag calls"() {
expect:
tagLib.hello().toString() == 'Hello World'
tagLib.hello(name: 'Fred').toString() == 'Hello Fred'
tagLib.bye(author: new Author(name: 'Fred')).toString == 'Bye Fred'
}
}
Alternatively, you can use the TestMixin
annotation and mock multiple tag libraries using the mockTagLib()
method:
import spock.lang.Specification
import grails.test.mixin.TestMixin
import grails.test.mixin.web.GroovyPageUnitTestMixin
@TestMixin(GroovyPageUnitTestMixin)
class MultipleTagLibSpec extends Specification {
void "test multiple tags"() {
given:
mockTagLib(SomeTagLib)
mockTagLib(SomeOtherTagLib)
expect:
// ...
}
}
The GroovyPageUnitTestMixin
provides convenience methods for asserting that the template output equals or matches an expected value.
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(SimpleTagLib)
class SimpleTagLibSpec extends Specification {
void "test hello tag"() {
expect:
assertOutputEquals ('Hello World', '<s:hello />')
assertOutputMatches (/.*Fred.*/, '<s:hello name="Fred" />')
}
}
Testing View and Template Rendering
You can test rendering of views and templates in grails-app/views
via the render(Map)
method provided by GroovyPageUnitTestMixin
:
import spock.lang.Specification
import grails.test.mixin.TestMixin
import grails.test.mixin.web.GroovyPageUnitTestMixin
@TestMixin(GroovyPageUnitTestMixin)
class RenderingSpec extends Specification {
void "test rendering template"() {
when:
def result = render(template: '/simple/hello')
then:
result == 'Hello World!'
}
}
This will attempt to render a template found at the location grails-app/views/simple/_hello.gsp
. Note that if the template depends on any custom tag libraries you need to call mockTagLib
as described in the previous section.
Some core tags use the active controller and action as input. In GroovyPageUnitTestMixin tests, you can manually set the active controller and action name by setting controllerName and actionName properties on the webRequest object:
webRequest.controllerName = 'simple'
webRequest.actionName = 'hello'