我想要做的是测试一个身份验证处理程序,但是我的问题归结为注册表中没有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
}
}(额外的重新抛出允许我们看到在棘轮包测试中抛出的异常,因为默认情况下它会被捕获并存储在结果中。)
我知道原则上我可以创建一个会话实例并使用一个registry { add <Session instance> }块将它添加到注册表中,但我已经深入研究了Ratpack代码,创建会话对象需要获取许多不同的其他组件并将它们传递给SessionModule#sessionAdaptor (或DefaultSession构造函数)。我找不到这样做的任何例子,看来这个调用是由Guice依赖注入魔术处理的,我无法取消。
在应用程序中,通常的方法是使用bind { module SessionModule }块,但这在RequestFixture#execute的上下文中是不可访问的。
由于会话对于任何web应用程序来说都是谋生手段,我的预感是这可能是一个很容易解决的问题,我只是还没有找到正确的方法来做呢?
发布于 2018-06-12 11:04:50
您可以通过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的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]
}
}希望能帮上忙。
https://stackoverflow.com/questions/50814817
复制相似问题