【问题标题】:How to test a Grails service that retrieves information from the HTTP session如何测试从 HTTP 会话中检索信息的 Grails 服务
【发布时间】:2017-03-09 19:55:25
【问题描述】:

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

此时我的目标是简单地编写一个测试来证明 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

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

【问题讨论】:

  • 与您的问题无关,但您不需要事务来获得会话,您正在打开与数据库的连接并且对您的 getSession() 无任何操作@
  • 没有充分的理由让服务提供其他服务将调用的getSession 方法。任何服务都可以实现grails.web.api.ServletAttributes,然后在该服务代码中可以简单地引用session。

标签: grails integration-testing grails3


【解决方案1】:

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'
    }
}

【讨论】:

  • 实现 ServletAttributes 可以让服务访问 htto 会话
  • 对。它旨在做到这一点。这就是控制器访问会话的方式。在编译时,我们将ServletAttributes 添加到所有控制器类中,并发布该特征,以便您可以在其他类中酌情使用它。
【解决方案2】:

最简单的方法是mock getSession 方法并返回会话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()
    }

【讨论】:

  • 这不是一个好的答案。问题包括“我此时的目标是简单地编写一个测试来证明 utilityService.getSession() 正在返回一些东西。”。此答案中提供的解决方案完全避免调用正在测试的方法。本次测试只是测试测试,不测试服务中的代码。
猜你喜欢
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
相关资源
最近更新 更多