package org.zalando.riptide.capture;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.AsyncRestTemplate;
import org.zalando.riptide.Rest;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import static org.zalando.riptide.Bindings.anyStatus;
import static org.zalando.riptide.Bindings.on;
import static org.zalando.riptide.Navigators.status;
import static org.zalando.riptide.Route.pass;
public final class CaptureTest {
@Rule
public final ExpectedException exception = ExpectedException.none();
private final Rest unit;
private final MockRestServiceServer server;
public CaptureTest() {
final AsyncRestTemplate template = new AsyncRestTemplate();
this.server = MockRestServiceServer.createServer(template);
this.unit = Rest.builder()
.requestFactory(template.getAsyncRequestFactory())
.converter(createJsonConverter())
.converter(new StringHttpMessageConverter())
.baseUrl("https://api.example.com")
.build();
}
private MappingJackson2HttpMessageConverter createJsonConverter() {
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(new ObjectMapper().findAndRegisterModules());
return converter;
}
@Test
public void shouldCapture() {
server.expect(requestTo("https://api.example.com/accounts/123")).andRespond(
withSuccess()
.body(new ClassPathResource("message.json"))
.contentType(APPLICATION_JSON));
final Capture<ObjectNode> capture = Capture.empty();
final CompletableFuture<Void> future = unit.get("/accounts/123")
.dispatch(status(),
on(OK).call(ObjectNode.class, capture),
anyStatus().call(this::fail));
final ObjectNode node = future.thenApply(capture).join();
assertThat(node.get("message").asText(), is("Hello World!"));
}
@Test
public void shouldCaptureNull() {
final HttpHeaders headers = new HttpHeaders();
headers.setContentLength(0);
server.expect(requestTo("https://api.example.com/null"))
.andRespond(withSuccess().headers(headers));
final Capture<String> capture = Capture.empty();
final CompletableFuture<Void> future = unit.get("/null")
.dispatch(status(),
on(OK).call(String.class, capture),
anyStatus().call(this::fail));
final String body = future.thenApply(capture).join();
assertThat(body, is(nullValue()));
}
@Test
public void shouldFail() {
server.expect(requestTo("https://api.example.com/accounts/123")).andRespond(withSuccess());
final Capture<String> capture = Capture.empty();
final CompletableFuture<String> future = unit.get("/accounts/123")
.dispatch(status(),
on(OK).call(pass()),
on(BAD_REQUEST).call(String.class, capture),
anyStatus().call(this::fail))
.thenApply(capture);
exception.expect(CompletionException.class);
exception.expectCause(instanceOf(NoSuchElementException.class));
future.join();
}
private void fail(final ClientHttpResponse response) throws IOException {
throw new AssertionError(response.getRawStatusCode());
}
}