Grails Unit Test Filters with the injected Service

04 / Aug / 2014 by Neha Gupta 0 comments

Recently I was writing unit tests for a filter in my project, which makes use of a service.

Normally mocking using ‘metaclass’ and ‘demand’ doesn’t work for services in filter, because filters don’t let mock the service methods like we do in other classes or controller.

Suppose we have a filter like:

[java]
class SomeFilters {

SomeService someService

def filters = {
all(controller: ‘*’, action: ‘*’) {
before = {
if (params.checkSomeValue) {
someService.serviceMethod(params.checkSomeValue)
redirect(controller: ‘some’, action: ‘index’)
}
return true
}
}
}
}
[/java]

and a Controller and the service like:
[java]
class SomeController {

def index() {
render "this is index"
}
}
[/java]

[java]
import grails.transaction.Transactional

@Transactional
class SomeService {

def serviceMethod(String check) {
println "this is the Service Method "+check
}
}
[/java]

To test the above mentioned filter using Grails spock we need to first mock the service. We can mock the service like:
[java]
class MockedSomeService extends SomeService {
@Override
def serviceMethod(String check) {
println "this is the Service Method " + check
}
}
[/java]

all we need to do is to create a class which will extend the service class.
Now the question arises, how’ll we inject this mocked service class for our test cases.
Here’s answer to this question.
[java]
defineBeans {
someService(MockedSomeService)
}
[/java]

this ‘defineBeans’ closure helps us to inject the service with the new definition specified by the mocked class. Here, our service ‘someService’ will use ‘MockedSomeService’ as its definition, i.e. overriding the original definition ‘SomeService’.

What’s next? This is it, now we can write rest of the test case as we do for normal filters.
[java]
@Mock([SomeFilters, SomeService])
@TestFor(SomeController)
class SomeFiltersSpec extends Specification {

void "test the filter"() {
setup:
defineBeans {
someService(MockedSomeService)
}
//mock other methods and variables here

when:
params.checkSomeValue = ‘checkSomeValue’
withFilters(controller: "*", action: "*") {
controller.index()
}

then:
assert response.status == 302
assert response.redirectedUrl == "/some/index"
}
}

class MockedSomeService extends SomeService {
@Override
def serviceMethod(String check) {
println "this is the Service Method " + check
}
}
[/java]

Dont forget to add the important annotations, i.e.,
[java]
@Mock([SomeFilters, SomeService])
@TestFor(SomeController)
[/java]

I hope you wont find it too difficult to test the filters with services.

You can also find the demo here.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *