thisdotnull
thisdotnull

Reputation: 862

Micronaut: Unable to test Redirect response with junit

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

Answers (2)

thisdotnull
thisdotnull

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

Shankha057
Shankha057

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 asserting 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

Related Questions