我要做的是测试身份验证处理程序,但我的问题归结为在注册表中没有Session
实例。
示例测试:
package whatever
import groovy.transform.CompileStatic
import ratpack.groovy.handling.GroovyChainAction
import ratpack.groovy.test.handling.GroovyRequestFixture
import ratpack.http.Status
import ratpack.session.Session
import spock.lang.Specification
class SessionChainTest extends Specification {
GroovyChainAction sessionChain = new GroovyChainAction() {
@Override
@CompileStatic
void execute() throws Exception {
get('foo') {
Session s = get Session
// Stuff using session here
}
}
}
def "should get session"() {
given:
def result = GroovyRequestFixture.handle(sessionChain) {
uri 'foo'
method 'GET'
}
expect:
result.status == Status.OK
// If the server threw, rethrow that
Throwable t = result.exception(Throwable)
if (t) throw t // <<< Throws NotInRegistryException because no Session in registry
}
}
(额外的重新抛出是为了让我们看到在ratpack测试中抛出的异常,因为默认情况下会在结果中捕获并隐藏它。)
我知道原则上我可以创建一个Session实例并使用registry { add <Session instance> }
块将其添加到注册表中,但我已经深入研究了Ratpack代码,并且创建一个Session对象需要获得很多不同的内容其他组件并将它们传递给SessionModule#sessionAdaptor
(或DefaultSession
构造函数)。我找不到任何关于这样做的例子,看来这个调用是由Guice依赖注入魔法处理的,我无法解开。
在应用程序中执行此操作的常用方法是使用bind { module SessionModule }
块,但无法从RequestFixture#execute
的上下文访问。
由于会话对于任何Web应用程序来说都是必不可少的,我的预感是,这可能是一个容易解决的问题,我还没找到正确的方法来做这件事?
答案 0 :(得分:1)
您可以通过Registry
方法调用访问GroovyRequestFixture.handle(handler, closure)
,例如,注册模拟Session
对象:
GroovyRequestFixture.handle(sessionChain) {
uri 'foo'
method 'GET'
registry { r ->
r.add(Session, session)
}
}
看一下下面的例子:
import groovy.transform.CompileStatic
import ratpack.exec.Promise
import ratpack.groovy.handling.GroovyChainAction
import ratpack.groovy.test.handling.GroovyRequestFixture
import ratpack.http.Status
import ratpack.jackson.internal.DefaultJsonRender
import ratpack.session.Session
import spock.lang.Specification
import static ratpack.jackson.Jackson.json
class SessionChainTest extends Specification {
Session session = Mock(Session) {
get('test') >> Promise.value(Optional.of('Lorem ipsum'))
}
GroovyChainAction sessionChain = new GroovyChainAction() {
@Override
@CompileStatic
void execute() throws Exception {
get('foo') {
Session s = get Session
s.get('test').map { Optional<String> o ->
o.orElse(null)
}.flatMap { value ->
Promise.value(value)
}.then {
render(json([message: it]))
}
}
}
}
def "should get session"() {
given:
def result = GroovyRequestFixture.handle(sessionChain) {
uri 'foo'
method 'GET'
registry { r ->
r.add(Session, session)
}
}
expect:
result.status == Status.OK
and:
result.rendered(DefaultJsonRender).object == [message: 'Lorem ipsum']
}
}
在此测试中,我模拟了Session
对象,以便键test
存储Lorem ipsum
文本。运行此测试时,两个断言都会通过。
Guice.registry()
如果您不想使用模拟的Session
对象,可以尝试使用Guice注册表对象替换默认的Ratpack&#39; Registry
。首先,初始化一个创建Guice注册表的函数,并通过绑定添加SessionModule
:
static Function<Registry, Registry> guiceRegistry = Guice.registry { bindings ->
bindings.module(new SessionModule())
}
接下来execute()
GroovyChainAction
register(guiceRegistry.apply(registry))
方法,您可以通过调用以下内容来替换默认注册表:
Session
不再进行模拟,但在这种情况下,您无法访问请求范围外的import groovy.transform.CompileStatic
import ratpack.exec.Promise
import ratpack.func.Function
import ratpack.groovy.handling.GroovyChainAction
import ratpack.groovy.test.handling.GroovyRequestFixture
import ratpack.guice.Guice
import ratpack.http.Status
import ratpack.jackson.internal.DefaultJsonRender
import ratpack.registry.Registry
import ratpack.session.Session
import ratpack.session.SessionModule
import spock.lang.Specification
import static ratpack.jackson.Jackson.json
class SessionChainTest extends Specification {
static Function<Registry, Registry> guiceRegistry = Guice.registry { bindings ->
bindings.module(new SessionModule())
}
GroovyChainAction sessionChain = new GroovyChainAction() {
@Override
@CompileStatic
void execute() throws Exception {
register(guiceRegistry.apply(registry))
get('foo') {
Session s = get Session
s.get('test').map { Optional<String> o ->
o.orElse(null)
}.flatMap { value ->
Promise.value(value)
}.then {
render(json([message: it]))
}
}
}
}
def "should get session"() {
given:
def result = GroovyRequestFixture.handle(sessionChain) {
uri 'foo'
method 'GET'
}
expect:
result.status == Status.OK
and:
result.rendered(DefaultJsonRender).object == [message: null]
}
}
对象,因此您无法在测试的准备阶段向会话添加任何内容。您可以在下面找到完整的示例:
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
ByteArrayOutputStream obj=new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(obj);
gzip.write(request.getBytes("UTF-8"));
gzip.close();
}
希望它有所帮助。