diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..9706c65 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..6e1225c --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,39 @@ + + + + + + true + *;static *;java;javax;org.springframework;uk.ac.fife + true + 1 + true + true + true + true + true + true + 1 + none + 4 + 4 + 8 + 80 + true + project + true + ORDERED_IN_CATEGORY + false + false + + diff --git a/pom.xml b/pom.xml index ab0ebe7..3af9d95 100644 --- a/pom.xml +++ b/pom.xml @@ -11,28 +11,8 @@ https://github.com/kemitix/wiser-assertions - - - Paul Campbell - pcampbell@kemitix.net - Kemitix - https://github.com/kemitix/ - - - - - - MIT License - http://www.opensource.org/licenses/mit-license.php - - - 2015 - - 3.0.4 - - https://github.com/kemitix/wiser-assertions/issues GitHub Issues @@ -46,14 +26,12 @@ UTF-8 - 1.8 - 1.8 - org.sonatype.oss - oss-parent - 9 + net.kemitix + kemitix-spring-parent + 1.1.7 @@ -69,57 +47,4 @@ - - - release-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - ${gpg.passphrase} - - - - sign-artifacts - verify - - sign - - - - - - - - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.4 - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.3 - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - - - \ No newline at end of file diff --git a/src/main/java/net/kemitix/wiser/assertions/WiserAssertions.java b/src/main/java/net/kemitix/wiser/assertions/WiserAssertions.java index 5d93ae9..9ed4f29 100644 --- a/src/main/java/net/kemitix/wiser/assertions/WiserAssertions.java +++ b/src/main/java/net/kemitix/wiser/assertions/WiserAssertions.java @@ -1,61 +1,145 @@ package net.kemitix.wiser.assertions; +import org.subethamail.wiser.Wiser; +import org.subethamail.wiser.WiserMessage; + import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.text.MessageFormat; import java.util.List; import java.util.function.Predicate; import java.util.function.Supplier; + import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import org.subethamail.wiser.Wiser; -import org.subethamail.wiser.WiserMessage; /** - * Taken from the WiserAssetions class from Rafal Browiec at - * http://blog.codeleak.pl/2014/09/testing-mail-code-in-spring-boot.html + * Provides a set of assertions for checking the status of any messages received + * by subethamail's Wiser. + * + *
+ * {@code
+ * {@literal @}Before
+ * public void setUp() throws IOException {
+ *     wiser = new Wiser(PORT);
+ *     wiser.start();
+ * }
+ *
+ * {@literal @}After public void tearDown() { wiser.stop(); }
+ *
+ * {@literal @}Test public void testMail() { //given ...
+ *
+ * //when ...
+ *
+ * //then WiserAssertions.assertReceivedMessage(wiser) .from(sender)
+ * .to(recipient_alpha) .to(recipient_beta) .withSubjectContains(subject_prefix)
+ * .withSubjectContains(subject_suffix) .withContentContains(message_element_1)
+ * .withContentContains(message_element_2)
+ * .withContentContains(message_element_3); }
+ * }
+ * 
*/ -public class WiserAssertions { +public final class WiserAssertions { + /** + * The messages received by Wiser. + */ private final List messages; - public static WiserAssertions assertReceivedMessage(Wiser wiser) { + /** + * Creates an instance of {@code} WiserAssertions} ready to make assertions + * on any messages received by the {@link Wiser} server. + * + * @param wiser the SMTP server instance + * + * @return an instance of {@code WiserAssertions} + */ + public static WiserAssertions assertReceivedMessage(final Wiser wiser) { return new WiserAssertions(wiser.getMessages()); } - private WiserAssertions(List messages) { - this.messages = messages; + /** + * Private constructor. + * + * @param wiserMessages the messages to be tested by the assertions + */ + private WiserAssertions(final List wiserMessages) { + this.messages = wiserMessages; } - public WiserAssertions from(String from) { - findFirstOrElseThrow(m -> m.getEnvelopeSender().equals(from), - assertionError("No message from [{0}] found!", from)); + /** + * Checks that there was at least one email received that was sent from the + * {@code sender}. + * + * @param sender email address to search for + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions from(final String sender) { + findFirstOrElseThrow(m -> m.getEnvelopeSender().equals(sender), + assertionError("No message from [{0}] found!", sender)); return this; } - public WiserAssertions to(String to) { - findFirstOrElseThrow(m -> m.getEnvelopeReceiver().equals(to), - assertionError("No message to [{0}] found!", to)); + /** + * Checks that there was at least one email received that was sent to the + * {@code recipient}. + * + * @param recipient email address to search for + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions to(final String recipient) { + findFirstOrElseThrow(m -> m.getEnvelopeReceiver().equals(recipient), + assertionError("No message to [{0}] found!", recipient)); return this; } - public WiserAssertions withSubject(String subject) { - Predicate predicate = m -> subject.equals(unchecked(getMimeMessage(m)::getSubject)); + /** + * Checks that there was at least one email received that has the required + * subject. + * + * @param subject the subject line to search for + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions withSubject(final String subject) { + Predicate predicate + = m -> subject.equals(unchecked(getMimeMessage(m)::getSubject)); findFirstOrElseThrow(predicate, - assertionError("No message with subject [{0}] found!", subject)); + assertionError("No message with subject [{0}] found!", + subject)); return this; } - public WiserAssertions withSubjectContains(String subject) { - Predicate predicate = m -> unchecked(getMimeMessage(m)::getSubject).contains(subject); + /** + * Checks that there was at least one email received that has a subject that + * contains the search text. + * + * @param subject the text to search for in the subject + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions withSubjectContains(final String subject) { + Predicate predicate + = m -> unchecked(getMimeMessage(m)::getSubject) + .contains(subject); findFirstOrElseThrow(predicate, - assertionError("No message with subject [{0}] found!", subject)); + assertionError("No message with subject [{0}] found!", + subject)); return this; } - public WiserAssertions withContent(String content) { + /** + * Check that there was at least one email received that has a body that + * matches the content. + * + * @param content the body of the email to search for + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions withContent(final String content) { findFirstOrElseThrow(m -> { ThrowingSupplier contentAsString = () -> getMimeMessageBody(m).trim(); @@ -64,21 +148,42 @@ public class WiserAssertions { return this; } - public WiserAssertions withContentContains(String content) { + /** + * Check that there was at least one email received that contains the search + * text. + * + * @param content the text to search for in the body of the email + * + * @return the {@code WiserAssertions} instance + */ + public WiserAssertions withContentContains(final String content) { StringBuilder messageContent = new StringBuilder(); findFirstOrElseThrow((WiserMessage m) -> { ThrowingSupplier contentAsString = () -> getMimeMessageBody(m).trim(); messageContent.append(unchecked(contentAsString)); return unchecked(contentAsString).contains(content); - }, assertionError("No message with content containing [{0}] found! Was {1}", content, messageContent)); + }, assertionError( + "No message with content containing [{0}] found! Was {1}", + content, messageContent)); return this; } - private String getMimeMessageBody(WiserMessage m) throws IOException, MessagingException { - Object content = getMimeMessage(m).getContent(); + /** + * Returns the body of the message. + * + * @param message the message + * + * @return the body of the message + * + * @throws IOException if error extracting the mime message + * @throws MessagingException if the message type is not known + */ + private String getMimeMessageBody(final WiserMessage message) + throws IOException, MessagingException { + Object content = getMimeMessage(message).getContent(); if (content instanceof MimeMessage) { - return (String) content; + return content.toString(); } if (content instanceof MimeMultipart) { return getMimeMultipartAsString((MimeMultipart) content); @@ -86,20 +191,63 @@ public class WiserAssertions { throw new RuntimeException("Unexpected MimeMessage content"); } - private void findFirstOrElseThrow(Predicate predicate, Supplier exceptionSupplier) { + /** + * Checks that at least on message matches the predicate or the supplied + * exception will be thrown. + * + * @param predicate the condition a message must match + * @param exceptionSupplier the supplier of the exception + */ + private void findFirstOrElseThrow( + final Predicate predicate, + final Supplier exceptionSupplier + ) { messages.stream().filter(predicate) .findFirst().orElseThrow(exceptionSupplier); } - private MimeMessage getMimeMessage(WiserMessage wiserMessage) { + /** + * Returns the mime message within the {@link WiserMessage} converting any + * {@link MessagingException}s into {@link RuntimeException}s. + * + * @param wiserMessage the message + * + * @return the mime message + */ + private MimeMessage getMimeMessage(final WiserMessage wiserMessage) { return unchecked(wiserMessage::getMimeMessage); } - private static Supplier assertionError(String errorMessage, Object... args) { - return () -> new AssertionError(MessageFormat.format(errorMessage, args)); + /** + * Returns a {@link Supplier} for an {@link AssertionError}. + * + * @param errorMessage the message for the exception + * @param args the parameters to insert into the message using + * {@link MessageFormat} + * + * @return a supplier of an {@link AssertionError} + */ + @SuppressWarnings( + {"ThrowableInstanceNotThrown", "ThrowableInstanceNeverThrown"}) + private static Supplier assertionError( + final String errorMessage, + final Object... args + ) { + return () + -> new AssertionError(MessageFormat.format(errorMessage, args)); } - public static T unchecked(ThrowingSupplier supplier) { + /** + * Convert any checked Exceptions into unchecked Exceptions. + * + * @param the item type to be returned after suppressing any + * checked exceptions + * @param supplier the source of the return value that could cause a checked + * exception + * + * @return the product of the supplier + */ + public static T unchecked(final ThrowingSupplier supplier) { try { return supplier.get(); } catch (Throwable e) { @@ -107,14 +255,38 @@ public class WiserAssertions { } } - private String getMimeMultipartAsString(MimeMultipart mimeMultipart) throws MessagingException, IOException { - OutputStream os = new ByteArrayOutputStream(); + /** + * Converts a {@link MimeMultipart} into a {@link String}. + * + * @param mimeMultipart the message part to convert + * + * @return the message part as a string + * + * @throws MessagingException if the part is empty + * @throws IOException if there is another error + */ + private String getMimeMultipartAsString(final MimeMultipart mimeMultipart) + throws MessagingException, IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); mimeMultipart.writeTo(os); - return os.toString(); + return os.toString("UTF-8"); } + /** + * Interface for providing a value that could thrown an exception when + * sought. + * + * @param the type of value to be supplied + */ public interface ThrowingSupplier { + /** + * Returns the value. + * + * @return the value + * + * @throws Throwable on error + */ T get() throws Throwable; } } diff --git a/src/main/java/net/kemitix/wiser/assertions/package-info.java b/src/main/java/net/kemitix/wiser/assertions/package-info.java new file mode 100644 index 0000000..f459df7 --- /dev/null +++ b/src/main/java/net/kemitix/wiser/assertions/package-info.java @@ -0,0 +1,28 @@ +/** + * Provides {@link WiserAssertions} to check for messages received by the Wiser + * SMTP test server from subethamail. + * + *

+ * The MIT License. + *

+ * Copyright 2015 pcampbell. + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.kemitix.wiser.assertions;