如何测试从 HTTP 会话中检索信息的 Grails 服务

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

我正在尝试为 Grails 网络插件编写测试。该插件包含一个服务 (UtilityService),它有一个名为 getSession() 的函数,returns GrailsHttpSession。其他服务使用它来 read/write 会话中的值。代码工作正常,但是当我尝试为使用返回的会话对象的任何函数编写测试时,测试失败。

此时我的目标是简单地编写一个测试来证明 utilityService.getSession() 正在返回一些东西。

我目前正在使用 Grails 3.2.7

实用服务:

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
    }

}

测试:

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()
    }
}

测试输出:

Condition not satisfied:

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

问题: 我需要做些什么才能使会话在测试环境中可用吗?是否可以在单元测试中执行此操作,还是必须是集成测试?

最简单的方法是mock getSession方法和return session mock(或Grails GrailsMockHttpSession),很简单Groovy:

@TestFor(SessionService)
class SessionMockSpec extends Specification {

    GrailsHttpSession session

    def setup() {
        session = Mock()
        service.metaClass.getSession = { session }
    }

    def 'should return session'() {
        expect:
            service.getSession()
    }

https://github.com/jeffbrown/mikegostomskiplugin 上的项目演示了一种方法。

https://github.com/jeffbrown/mikegostomskiplugin/blob/5dcb2953f1dc8eb20deefb26cdfa54e6f77617e6/grails-app/services/psu/util/UtilityService.groovy

package psu.util

import grails.web.api.ServletAttributes

class UtilityService implements ServletAttributes {

    def getSomethingFromSession(String key) {
        session[key]
    }
}

https://github.com/jeffbrown/mikegostomskiplugin/blob/5dcb2953f1dc8eb20deefb26cdfa54e6f77617e6/src/test/groovy/psu/util/UtilityServiceSpec.groovy

package psu.util

import grails.test.mixin.TestFor
import grails.test.mixin.TestMixin
import grails.test.mixin.web.ControllerUnitTestMixin
import spock.lang.Specification

@TestFor(UtilityService)
@TestMixin(ControllerUnitTestMixin)
class UtilityServiceSpec extends Specification {

    void 'test interacting with session'() {
        when:
        session.'Some Session Key' = 'King Crimson Is Awesome'

        then:
        service.getSomethingFromSession('Some Session Key') == 'King Crimson Is Awesome'
    }
}