package com.wesabe.servlet.errors.tests;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;
import static org.mockito.Mockito.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.wesabe.servlet.errors.ErrorReporter;
@RunWith(Enclosed.class)
public class ErrorReporterTest {
private static class FakeErrorReporter extends ErrorReporter {
private final List<Message> messages = Lists.newLinkedList();
public FakeErrorReporter(String from, String to, String serviceName)
throws AddressException {
super(from, to, serviceName);
}
@Override
public void deliver(Message message, HttpServletRequest request,
HttpServletResponse response, Throwable e) throws IOException, MessagingException {
messages.add(message);
}
@Override
public Session getSession() {
return null;
}
public List<Message> getMessages() {
return messages;
}
}
public static class An_Error_Reporter {
private ErrorReporter reporter;
@Before
public void setup() throws Exception {
this.reporter = new FakeErrorReporter("from@example.com", "to@example.com", "system");
}
@Test
public void itHasASender() throws Exception {
assertThat(
reporter.getSenders(),
is((List<InternetAddress>) ImmutableList.of(InternetAddress.parse("from@example.com")))
);
}
@Test
public void itHasARecipient() throws Exception {
assertThat(
reporter.getRecipients(),
is((List<InternetAddress>) ImmutableList.of(InternetAddress.parse("to@example.com")))
);
}
@Test
public void itHasAServiceName() throws Exception {
assertThat(reporter.getServiceName(), is("system"));
}
}
public static class The_Email_Sent_When_An_Exception_Is_Thrown {
private HttpServletRequest request;
private HttpServletResponse response;
private FakeErrorReporter reporter;
private String email;
private Throwable exception;
private MimeMessage message;
@Before
public void setup() throws Exception {
this.request = mock(HttpServletRequest.class);
when(request.getRequestURL()).thenReturn(new StringBuffer("http://example.com/thing"));
when(request.toString()).thenReturn(
"GET /thing HTTP/1.1\n" +
"User-Agent: A Unit Test\n" +
"Authorization: Basic SNUPERSNEAKY"
);
when(request.getRemoteAddr()).thenReturn("123.89.11.19");
this.response = mock(HttpServletResponse.class);
this.reporter = new FakeErrorReporter("exceptions@example.com", "developers@example.com", "unittest");
try {
throw new RuntimeException("THE BEES THEY'RE IN MY EYES");
} catch (final RuntimeException exception) {
this.exception = exception;
reporter.report(request, response, exception);
this.message = (MimeMessage) reporter.getMessages().get(0);
final ByteArrayOutputStream output = new ByteArrayOutputStream();
message.writeTo(output);
this.email = output.toString();
}
}
@Test
public void itIsFromTheSpecifiedAddress() throws Exception {
assertThat(email, containsString("From: exceptions@example.com"));
}
@Test
public void itIsToTheSpecifiedRecipient() throws Exception {
assertThat(email, containsString("To: developers@example.com"));
}
@Test
public void itHasADescriptiveSubject() throws Exception {
assertThat(email, containsString("Subject: [ERROR] unittest threw a RuntimeException"));
}
@Test
public void itHasTheClientsIpAddress() throws Exception {
assertThat(email, containsString("123.89.11.19"));
}
@Test
public void itHasTheRequest() throws Exception {
assertThat(email, containsString("GET /thing HTTP/1.1"));
assertThat(email, containsString("User-Agent: A Unit Test"));
}
@Test
public void itRedactsAuthorizationCredentials() throws Exception {
assertThat(email, containsString("Authorization: [REDACTED]"));
}
@Test
public void itSendsPlainUTF8() throws Exception {
assertThat(email, containsString("Content-Type: text/plain; charset=UTF-8"));
}
@Test
public void itHasTheExceptionStackTrace() throws Exception {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final PrintWriter writer = new PrintWriter(output);
exception.printStackTrace(writer);
assertThat(email, containsString(output.toString()));
}
}
}