package org.zalando.riptide; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpResponse; import org.springframework.test.web.client.MockRestServiceServer; import org.zalando.fauxpas.ThrowingConsumer; import org.zalando.fauxpas.ThrowingRunnable; import org.zalando.riptide.model.AccountBody; import java.io.IOException; import java.net.URI; import java.util.concurrent.CompletionException; import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; 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.responseEntityOf; public final class CallTest { @Rule public final ExpectedException exception = ExpectedException.none(); private final URI url = URI.create("https://api.example.com/accounts/123"); private final Rest unit; private final MockRestServiceServer server; public CallTest() { final MockSetup setup = new MockSetup("https://api.example.com/"); this.unit = setup.getRest(); this.server = setup.getServer(); } @Test public void shouldCallEntity() throws Exception { server.expect(requestTo(url)).andRespond( withSuccess() .body(new ClassPathResource("account.json")) .contentType(APPLICATION_JSON)); @SuppressWarnings("unchecked") final ThrowingConsumer<AccountBody, Exception> verifier = mock(ThrowingConsumer.class); unit.get("accounts/123") .dispatch(status(), on(OK).call(AccountBody.class, verifier), anyStatus().call(this::fail)); verify(verifier).tryAccept(any(AccountBody.class)); } @Test public void shouldCallResponseEntity() throws Exception { server.expect(requestTo(url)).andRespond( withSuccess() .body(new ClassPathResource("account.json")) .contentType(APPLICATION_JSON)); @SuppressWarnings("unchecked") final ThrowingConsumer<ResponseEntity<AccountBody>, Exception> verifier = mock(ThrowingConsumer.class); unit.get("accounts/123") .dispatch(status(), on(OK).call(responseEntityOf(AccountBody.class), verifier), anyStatus().call(this::fail)); @SuppressWarnings("unchecked") final ArgumentCaptor<ResponseEntity<AccountBody>> captor = ArgumentCaptor.forClass(ResponseEntity.class); verify(verifier).tryAccept(captor.capture()); final ResponseEntity<AccountBody> entity = captor.getValue(); assertThat(entity.getStatusCode(), is(OK)); assertThat(entity.getHeaders(), is(not(anEmptyMap()))); assertThat(entity.getBody().getName(), is("Acme Corporation")); } @Test public void shouldCallWithoutParameters() throws Exception { server.expect(requestTo(url)).andRespond( withSuccess() .body(new ClassPathResource("account.json")) .contentType(APPLICATION_JSON)); @SuppressWarnings("unchecked") final ThrowingRunnable<Exception> verifier = mock(ThrowingRunnable.class); unit.get("accounts/123") .dispatch(status(), on(OK).call(verifier), anyStatus().call(this::fail)); verify(verifier).tryRun(); } @Test public void shouldThrowCheckedExceptionOnEntity() { server.expect(requestTo(url)).andRespond( withSuccess() .body(new ClassPathResource("account.json")) .contentType(APPLICATION_JSON)); exception.expect(CompletionException.class); exception.expectCause(instanceOf(IOException.class)); unit.get("accounts/123") .dispatch(status(), on(OK).call(AccountBody.class, this::validateEntity), anyStatus().call(this::fail)) .join(); } private void validateEntity(final AccountBody account) throws IOException { throw new IOException(); } private void fail(final ClientHttpResponse response) throws IOException { throw new AssertionError(response.getRawStatusCode()); } }