Reputation: 862
I am trying to test a redirect scenario where Controller is returning HttpResponse.seeOther(URI.create(redirectUri));
. The issue is my test case is following the redirect instead of returning HttpResponse<String>
or something equivalent. How to test this in Micronaut?
Controller
@Post("/some/endpoint")
public HttpResponse<?> capture(@Body Map<String, String> body)
throws Exception {
// do something
String uri = getRedirectUri();
return HttpResponse.seeOther(URI.create(redirectUri));
}
Test
@Test
public void testCapture() {
String expectedUri = getRedirectUri();
//following doesn't work
String redirectUrl = client.toBlocking().retrieve(HttpRequest.POST("/some/endpoint", body), String.class);
assertEquals(expectedUri, redirectUrl);
//following also doesn't work
HttpResponse<String> response = client.toBlocking().retrieve(HttpRequest.POST("/some/controller", someBody), HttpResponse.class);
assertEquals(HttpStatus.SEE_OTHER, response.status());
}
Error
16:59:32.321 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - HTTP Client Response Received for Request: POST http://localhost:65164/some/endpoint
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - Status Code: 303 See Other
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - Location: http://localhost:8080/target/location.html
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - Date: Wed, 13 Nov 2019 23:59:32 GMT
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - connection: close
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - Response Body
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - ----
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient -
16:59:32.322 [nioEventLoopGroup-1-3] TRACE i.m.http.client.DefaultHttpClient - ----
io.micronaut.http.client.exceptions.HttpClientException: Connect Error: Connection refused: localhost/127.0.0.1:8080
at io.micronaut.http.client.DefaultHttpClient.lambda$null$24(DefaultHttpClient.java:1035)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:504)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:483)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424)
at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:121)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:327)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:343)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:632)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8080
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:327)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340)
... 7 more
Caused by: java.net.ConnectException: Connection refused
... 11 more
Upvotes: 2
Views: 1600
Reputation: 862
Implemented a work around by using client.exchange()
method which returns a publisher. A io.reactivex.subscribers.TestSubscriber
can be used to subscribe and test for assertions.
HttpClient.exchange()
method signature-
<I, O> Publisher<HttpResponse<O>> exchange(HttpRequest<I> request, Class<O> bodyType) {...}
Working test case with TestSubscriber
-
@Test
public void testCapture() {
//Instead of using client.toBlocking().retrieve(...)
/*
String redirectUrl = client.toBlocking()
.retrieve(HttpRequest.POST("/some/endpoint", body), String.class);
*/
// Use client.exchange(...)
Publisher<HttpResponse<Object>> exchange =
client.exchange(HttpRequest.POST("/payment/1234567890/capture", body)
.contentType(MediaType.APPLICATION_FORM_URLENCODED), Object.class);
TestSubscriber<HttpResponse<?>> testSubscriber = new TestSubscriber<HttpResponse<?>>() {
@Override
public void onNext(HttpResponse<?> httpResponse) {
assertNotNull(httpResponse);
assertEquals(HttpStatus.SEE_OTHER, httpResponse.status());
assertEquals(getRedirectUri(), httpResponse.header("location"));
}
};
exchange.subscribe(testSubscriber);
// await to allow for response
testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS);
// assert for errors, completion, terminated etc.
testSubscriber.assertNoErrors();
testSubscriber.assertComplete();
testSubscriber.assertTerminated();
}
Upvotes: 2
Reputation: 1369
I tested certain scenarios, and observed that the Micronaut
client processes certain types of Response
(Http See Other, Bad Request, Server Error).
A workaround in your case is to try to get the object, which is given by the endpoint which the See Other
points to and assert
ing it.
But if really want to get the String
only then in the Controller
method, change your return to HttpResponse.status(HttpStatus.SEE_OTHER).body(URI.create(redirectUri);
Upvotes: 1