package org.zalando.problem.spring.web.advice;
import com.google.gag.annotation.remark.Hack;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import uk.org.lidalia.slf4jext.Level;
import uk.org.lidalia.slf4jtest.LoggingEvent;
import uk.org.lidalia.slf4jtest.TestLogger;
import uk.org.lidalia.slf4jtest.TestLoggerFactory;
import uk.org.lidalia.slf4jtest.TestLoggerFactoryResetRule;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
import java.util.Arrays;
import static com.google.common.collect.Iterables.getOnlyElement;
import static javax.ws.rs.core.Response.Status.Family.CLIENT_ERROR;
import static javax.ws.rs.core.Response.Status.Family.SERVER_ERROR;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
@RunWith(Parameterized.class)
public final class AdviceTraitLoggingTest {
private final TestLogger log = TestLoggerFactory.getTestLogger(AdviceTrait.class);
@Rule
public final TestLoggerFactoryResetRule rule = new TestLoggerFactoryResetRule();
@Parameter
public Status status;
private final AdviceTrait unit = new AdviceTrait() {
};
@Parameters(name = "{0}")
public static Iterable<Status> data() {
return Arrays.asList(Status.values());
}
@Test
public void shouldLog4xxAsWarn() {
assumeThat(status.getFamily(), is(CLIENT_ERROR));
unit.create(status, new NoHandlerFoundException("GET", "/", new HttpHeaders()), mock(NativeWebRequest.class));
final LoggingEvent event = getOnlyElement(log.getLoggingEvents());
assertThat(event.getLevel(), is(Level.WARN));
assertThat(event.getMessage(), is("{}: {}"));
assertThat(event.getArguments(), contains(getReasonPhrase(status), "No handler found for GET /"));
assertThat(event.getThrowable().orNull(), is(nullValue()));
}
@Test
public void shouldLog5xxAsError() {
assumeThat(status.getFamily(), is(SERVER_ERROR));
final IOException throwable = new IOException();
unit.create(status, throwable, mock(NativeWebRequest.class));
final LoggingEvent event = getOnlyElement(log.getLoggingEvents());
assertThat(event.getLevel(), is(Level.ERROR));
assertThat(event.getMessage(), is(getReasonPhrase(status)));
assertThat(event.getArguments(), emptyIterable());
assertThat(event.getThrowable().orNull(), is(throwable));
}
@Hack("Because several status codes are defined with different reason phrases in Spring and JAX-RS")
public static String getReasonPhrase(final Status status) {
return HttpStatus.valueOf(status.getStatusCode()).getReasonPhrase();
}
}