What I'm trying to do is test an authentication handler, but my problem boils down to having no Session
instance in the registry.
An example test:
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
}
}
(The extra rethrow is in there to allow us to see the exception thrown within the ratpack test, because by default it is caught and stashed in the result.)
I know that in principle I could create a Session instance and add it to the registry with a registry { add <Session instance> }
block, but I've delved into the Ratpack code, and creating a Session object requires getting a lot of disparate other components and passing them to SessionModule#sessionAdaptor
(or the DefaultSession
constructor). I can't find any examples of that being done, it appears this call is handled by Guice dependency-injection magic I can't unpick.
The usual way to do it in an application is to use a bind { module SessionModule }
block but this isn't accessible from the context of RequestFixture#execute
.
As sessions are bread and butter for any web application, my hunch is that this may be an easily solved problem, I just haven't found the right way to do it?
You can access
Registry
throughGroovyRequestFixture.handle(handler, closure)
method call and you can e.g. register mockedSession
object:Take a look at following example:
In this test I mock
Session
object for keytest
to storeLorem ipsum
text. When running this test, both assertions pass.Alternative approach: registering
Guice.registry()
If you don't want to use mocked
Session
object you can try replacing default Ratpack'sRegistry
with a Guice registry object. Firstly, initialize a function that creates Guice registry and addSessionModule
via bindings:Next inside
execute()
method ofGroovyChainAction
you can replace the default registry by calling:No mocks anymore, but in this case you can't access
Session
object outside request scope, so you wont be able to add anything to the session in preparation stage of your test. Below you can find full example:Hope it helps.