package org.zalando.riptide.problem;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.zalando.fauxpas.ThrowingConsumer;
import org.zalando.problem.Exceptional;
import org.zalando.problem.ThrowableProblem;
import org.zalando.riptide.Rest;
import java.net.URI;
import java.util.concurrent.CompletionException;
import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.Series.SUCCESSFUL;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
import static org.zalando.riptide.Bindings.anySeries;
import static org.zalando.riptide.Bindings.on;
import static org.zalando.riptide.Navigators.series;
import static org.zalando.riptide.Route.pass;
import static org.zalando.riptide.problem.ProblemRoute.problemHandling;
@RunWith(MockitoJUnitRunner.class)
public final class ProblemRouteTest {
@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;
@Mock
private ThrowingConsumer<Exceptional, RuntimeException> consumer;
public ProblemRouteTest() {
final MockSetup setup = new MockSetup();
this.unit = setup.getRest();
this.server = setup.getServer();
}
@Test
public void shouldPropagateProblem() {
perform("application/problem+json");
}
@Test
public void shouldPropagateLegacyProblem() {
perform("application/x.problem+json");
}
@Test
public void shouldPropagateLegacyProblemWithAlternativeSpelling() {
perform("application/x-problem+json");
}
private void perform(final String mediaType) {
server.expect(requestTo(url))
.andRespond(withStatus(BAD_REQUEST)
.body(new ClassPathResource("problem.json"))
.contentType(MediaType.parseMediaType(mediaType)));
exception.expect(CompletionException.class);
exception.expectCause(instanceOf(ThrowableProblem.class));
unit.get(url)
.dispatch(series(),
on(SUCCESSFUL).call(pass()),
anySeries().call(problemHandling()))
.join();
}
@Test
public void shouldDelegateProblemHandling() {
server.expect(requestTo(url))
.andRespond(withStatus(BAD_REQUEST)
.body(new ClassPathResource("problem.json"))
.contentType(MediaType.parseMediaType("application/problem+json")));
unit.get(url)
.dispatch(series(),
on(SUCCESSFUL).call(pass()),
anySeries().call(problemHandling(consumer)))
.join();
verify(consumer).tryAccept(any());
}
}