grailsintegration-testinggrails3

How to test a Grails service that retrieves information from the HTTP session


I am trying to write tests for a Grails web-plugin. The plugin contains a service (UtilityService) which has a function called getSession() which returns the GrailsHttpSession. Other services use that to read/write values in the session. The code is working just fine, but when I try to write tests for any function that uses the returned session object, the tests fail.

My goal at this point is to simply write a test which proves that utilityService.getSession() is returning something.

I am currently working with Grails 3.2.7

UtilityService:

package psu.util

import grails.transaction.Transactional
import grails.core.GrailsApplication
import grails.util.Environment

import grails.core.*
import org.grails.web.util.WebUtils
import org.springframework.web.context.request.RequestContextHolder
import javax.servlet.http.HttpServletRequest

@Transactional
class UtilityService {
    GrailsApplication grailsApplication

    @Transactional(readOnly = true)
    grails.web.servlet.mvc.GrailsHttpSession getSession(){
        return WebUtils.retrieveGrailsWebRequest()?.session
    }

}

Test:

package psu.util

import grails.test.mixin.TestFor
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*

@Integration
@Rollback
@TestFor(UtilityService)
class UtilityServiceIntegrationSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test getSession"() {
        expect:
        service.getSession()
    }
}

Test Output:

Condition not satisfied:

service.getSession()
|       |
|       null
psu.util.UtilityService@28eab745

Questions: Is there something that I need to do to make the session available in the TEST environment? Is it possible to do this in a Unit test, or does it have to be an Integration test?


Solution

  • The easiest way is to mock getSession method and return session mock (or Grails GrailsMockHttpSession), its simple as that in Groovy:

    @TestFor(SessionService)
    class SessionMockSpec extends Specification {
    
        GrailsHttpSession session
    
        def setup() {
            session = Mock()
            service.metaClass.getSession = { session }
        }
    
        def 'should return session'() {
            expect:
                service.getSession()
        }