package org.zalando.catwatch.backend.scheduler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;
import org.zalando.catwatch.backend.CatWatchBackendApplication;
import org.zalando.catwatch.backend.mail.MailSender;
import javax.mail.internet.MimeMessage;
import java.text.MessageFormat;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(properties = {
"mail.port=2500",
"mail.host=localhost",
"mail.from=from@test.de",
"mail.to=to@test.de",
"fetcher.maxAttempts=1"})
@SpringApplicationConfiguration(classes = CatWatchBackendApplication.class)
public class MailSenderTest {
private Wiser wiser;
@Autowired
private MailSender mailSender;
@Mock
private Fetcher fetcher;
@Before
public void setUp() throws Exception {
wiser = new Wiser();
wiser.setPort(2500);
wiser.start();
}
@After
public void tearDown() throws Exception {
wiser.stop();
}
@Test
public void send() throws Exception {
mailSender.send(new RuntimeException());
// assert
WiserAssertions.assertReceivedMessage(wiser)
.from("from@test.de")
.to("to@test.de")
.withSubject("GitHub crawler failed to fetch data");
}
public static class WiserAssertions {
//
private final List<WiserMessage> messages;
public static WiserAssertions assertReceivedMessage(Wiser wiser) {
return new WiserAssertions(wiser.getMessages());
}
private WiserAssertions(List<WiserMessage> messages) {
this.messages = messages;
}
public WiserAssertions from(String from) {
findFirstOrElseThrow(m -> m.getEnvelopeSender().equals(from),
assertionError("No message from [{0}] found!", from));
return this;
}
public WiserAssertions to(String to) {
findFirstOrElseThrow(m -> m.getEnvelopeReceiver().equals(to),
assertionError("No message to [{0}] found!", to));
return this;
}
public WiserAssertions withSubject(String subject) {
Predicate<WiserMessage> predicate = m -> subject.equals(unchecked(getMimeMessage(m)::getSubject));
findFirstOrElseThrow(predicate,
assertionError("No message with subject [{0}] found!", subject));
return this;
}
public WiserAssertions withContent(String content) {
findFirstOrElseThrow(m -> {
ThrowingSupplier<String> contentAsString =
() -> ((String) getMimeMessage(m).getContent()).trim();
return content.equals(unchecked(contentAsString));
}, assertionError("No message with content [{0}] found!", content));
return this;
}
private void findFirstOrElseThrow(Predicate<WiserMessage> predicate, Supplier<AssertionError> exceptionSupplier) {
messages.stream().filter(predicate)
.findFirst().orElseThrow(exceptionSupplier);
}
private MimeMessage getMimeMessage(WiserMessage wiserMessage) {
return unchecked(wiserMessage::getMimeMessage);
}
private static Supplier<AssertionError> assertionError(String errorMessage, String... args) {
return () -> new AssertionError(MessageFormat.format(errorMessage, args));
}
public static <T> T unchecked(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
interface ThrowingSupplier<T> {
T get() throws Throwable;
}
}
}