Validate response status code of a redirect (HTTP 302 - Found) in Lagom service test

529 views
Skip to first unread message

Nico V L

unread,
Oct 5, 2017, 10:26:17 AM10/5/17
to Lagom Framework Users
Hi all,

The following sample Lagom service implementation just immediately respond with a redirect:

@Override
public ServerServiceCall<NotUsed, Done> doRedirect() {
    return HeaderServiceCall.of((requestHeader, notUsed) -> {
        // A redirecting response containing an extra header
        Location locationHeader = Location.create("http://www.non-existing-redirect-url.com");
        return CompletableFuture.completedFuture(Pair.create(ResponseHeader.OK.withStatus(StatusCodes.FOUND.intValue()).withHeader(locationHeader.name(), locationHeader.value()), Done.getInstance()));
    });
}

And the corresponding Junit test is:

@Test
public void shouldRedirect() throws ExecutionException, InterruptedException {
    Done done = requestService.doRedirect().invoke().toCompletableFuture().get();
    assertEquals(done, Done.getInstance());
}

But when I run this test, the following exception is thrown:
java.util.concurrent.ExecutionException: java.net.UnknownHostException: www.non-existing-redirect-url.com: unknown error
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1887)
at scala.concurrent.java8.FuturesConvertersImpl$CF.scala$concurrent$java8$FuturesConvertersImpl$CF$$super$get(FutureConvertersImpl.scala:82)
at scala.concurrent.java8.FuturesConvertersImpl$CF$$anonfun$get$1.apply(FutureConvertersImpl.scala:82)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.package$.blocking(package.scala:123)
at scala.concurrent.java8.FuturesConvertersImpl$CF.get(FutureConvertersImpl.scala:82)
at io.romcore.rscp.request.impl.RequestServiceImplTest.shouldRedirect(RequestServiceImplTest.java:518)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.net.UnknownHostException: www.non-existing-redirect-url.com: unknown error
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:907)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1302)
at java.net.InetAddress.getAllByName0(InetAddress.java:1255)
at java.net.InetAddress.getAllByName(InetAddress.java:1171)
at java.net.InetAddress.getAllByName(InetAddress.java:1105)
at play.shaded.ahc.io.netty.resolver.DefaultNameResolver.doResolveAll(DefaultNameResolver.java:48)
at play.shaded.ahc.io.netty.resolver.SimpleNameResolver.resolveAll(SimpleNameResolver.java:81)
at play.shaded.ahc.io.netty.resolver.InetNameResolver.resolveAll(InetNameResolver.java:68)
at play.shaded.ahc.io.netty.resolver.SimpleNameResolver.resolveAll(SimpleNameResolver.java:72)
at play.shaded.ahc.org.asynchttpclient.resolver.RequestHostnameResolver.resolve(RequestHostnameResolver.java:64)
at play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequestWithNewChannel(NettyRequestSender.java:284)
at play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequestWithCertainForceConnect(NettyRequestSender.java:136)
at play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequest(NettyRequestSender.java:107)
at play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendNextRequest(NettyRequestSender.java:473)
at play.shaded.ahc.org.asynchttpclient.netty.handler.intercept.Redirect30xInterceptor.exitAfterHandlingRedirect(Redirect30xInterceptor.java:153)
at play.shaded.ahc.org.asynchttpclient.netty.handler.intercept.Interceptors.exitAfterIntercept(Interceptors.java:86)
at play.shaded.ahc.org.asynchttpclient.netty.handler.HttpHandler.handleHttpResponse(HttpHandler.java:131)
at play.shaded.ahc.org.asynchttpclient.netty.handler.HttpHandler.handleRead(HttpHandler.java:185)
at play.shaded.ahc.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelRead(AsyncHttpClientHandler.java:76)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:356)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:335)
at play.shaded.ahc.io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:356)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:335)
at play.shaded.ahc.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:356)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:335)
at play.shaded.ahc.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
at play.shaded.ahc.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:295)
at play.shaded.ahc.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:282)
at play.shaded.ahc.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:398)
at play.shaded.ahc.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:250)
at play.shaded.ahc.io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:356)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:335)
at play.shaded.ahc.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:356)
at play.shaded.ahc.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
at play.shaded.ahc.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
at play.shaded.ahc.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at play.shaded.ahc.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at play.shaded.ahc.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at play.shaded.ahc.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at play.shaded.ahc.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at play.shaded.ahc.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131)
at play.shaded.ahc.io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:745)

I didn't expect Lagom tries to resolve the redirect url internally.

If you replace the unknown url with a valid one, no exception is thrown anymore, but how can I assert the status code (HTTP 302 - Found) in my test?

Thanks in advance,
Nico

Olivier Deckers

unread,
Oct 5, 2017, 12:07:22 PM10/5/17
to Lagom Framework Users
Have you tried adding 
play.ws.followRedirects = false
to your test/resources/application.conf file? 

Ignasi Marimon-Clos i Sunyol

unread,
Oct 6, 2017, 5:55:38 AM10/6/17
to Olivier Deckers, Lagom Framework Users
Hi Nico,

currently Lagom's client doesn't expose the wire protocol. That means you can't assert the repose contains a status header with a code 302 using lagom tools. You would have to use another http client like Play's WSClient for example:

    @Test
public void shouldStorePersonalizedGreeting() throws Exception {
withServer(defaultSetup().withCassandra(false).withCluster(false), server -> {
HelloService client = server.client(HelloService.class);

WSClient wsClient = server.injector().instanceOf(WSClient.class);
WSRequest request = wsClient.url("http://localhost:" + server.port() + "/api/redirect");
WSResponse wsResponse = FutureConverters.toJava(request.execute()).toCompletableFuture().get(5, TimeUnit.SECONDS);

assertEquals(302, wsResponse.status());
});
}
Hope this helps,



PS: note this code requires scala-java8-compat because WSClient returns a scala Future. Just use any http client.
libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-java8-compat" % "0.8.0"
)

--
You received this message because you are subscribed to the Google Groups "Lagom Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lagom-framework+unsubscribe@googlegroups.com.
To post to this group, send email to lagom-framework@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lagom-framework/016f3eb9-cd6c-4615-a59c-323bb6016706%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Ignasi Marimon-Clos
Software Developer @ Lagom


Reply all
Reply to author
Forward
0 new messages