AssertAttachment.java
package fr.sii.ogham.testing.assertion.email;
import static fr.sii.ogham.testing.assertion.util.EmailUtils.getAttachment;
import static fr.sii.ogham.testing.assertion.util.EmailUtils.getContent;
import fr.sii.ogham.testing.assertion.exception.MessageReadingException;
import ogham.testing.jakarta.mail.BodyPart;
import ogham.testing.jakarta.mail.Message;
import ogham.testing.jakarta.mail.MessagingException;
import ogham.testing.jakarta.mail.Multipart;
import fr.sii.ogham.testing.assertion.util.AssertionRegistry;
import fr.sii.ogham.testing.assertion.util.Executable;
import fr.sii.ogham.testing.assertion.util.FailAtEndRegistry;
import org.junit.jupiter.api.Assertions;
import java.io.IOException;
import java.util.function.Function;
/**
* Utility class for checking the attachment of the received email is as
* expected.
*
* @author Aurélien Baudet
*
*/
public final class AssertAttachment {
/**
* Shortcut for use with GreenMail. See
* {@link #assertEquals(ExpectedAttachment, Message)}.
*
* @param expected
* the expected attachment values
* @param actual
* the received email that must contain the attachment (the array
* must have only one email)
* @throws MessageReadingException
* when access to message has failed
*/
public static void assertEquals(ExpectedAttachment expected, Message[] actual) throws MessageReadingException {
AssertionRegistry registry = new FailAtEndRegistry();
registry.register(() -> Assertions.assertEquals(1, actual.length, "should have only one message"));
assertEquals(expected, actual.length == 1 ? actual[0] : null, registry);
registry.execute();
}
/**
* Checks if the received email contains the expected attachment. It also
* ensures that the values of the attachment are respected by checking:
* <ul>
* <li>The mimetype of the attachment</li>
* <li>The description of the attachment</li>
* <li>The disposition of the attachment</li>
* <li>The content of the attachment</li>
* </ul>
*
* @param expected
* the expected attachment values
* @param actual
* the received email that must contain the attachment
* @throws MessageReadingException
* when access to message has failed
*/
public static void assertEquals(ExpectedAttachment expected, Message actual) throws MessageReadingException {
AssertionRegistry registry = new FailAtEndRegistry();
assertEquals(expected, actual, registry);
registry.execute();
}
/**
* It ensures that the values of the received attachment are respected by
* checking:
* <ul>
* <li>The mimetype of the attachment</li>
* <li>The description of the attachment</li>
* <li>The disposition of the attachment</li>
* <li>The content of the attachment</li>
* </ul>
*
* @param expected
* the expected attachment values
* @param attachment
* the received attachment
* @throws AssertionError
* when there are unexpected differences
* @throws MessageReadingException
* when access to part has failed
*/
public static void assertEquals(ExpectedAttachment expected, BodyPart attachment) throws MessageReadingException {
AssertionRegistry registry = new FailAtEndRegistry();
assertEquals(expected, attachment, registry);
registry.execute();
}
private static void assertEquals(ExpectedAttachment expected, Message actual, AssertionRegistry registry) throws MessageReadingException {
try {
Object content = actual == null ? null : actual.getContent();
registry.register(() -> Assertions.assertTrue(content instanceof Multipart, "should be multipart message"));
BodyPart part = getAttachmentOrNull((Multipart) content, expected.getName(), registry);
assertEquals(expected, part, registry);
} catch(IOException | MessagingException e) {
throw new MessageReadingException("Failed to read content of the message", e);
}
}
private static void assertEquals(ExpectedAttachment expected, BodyPart attachment, AssertionRegistry registry) throws MessageReadingException {
// @formatter:off
try {
String prefix = "attachment named '" + expected.getName() + "'" + (attachment==null ? " (/!\\ not found)" : "");
String contentType = attachment == null || attachment.getContentType()==null ? null : attachment.getContentType();
registry.register(() -> Assertions.assertTrue(contentType!=null && expected.getMimetype().matcher(contentType).matches(),
prefix + " mimetype should match '" + expected.getMimetype() + "' but was " + (contentType==null ? "null" : "'" + contentType + "'")));
registry.register(() -> Assertions.assertEquals(expected.getDescription(),
attachment == null ? null : attachment.getDescription(),
prefix + " description should be '" + expected.getDescription() + "'"));
registry.register(() -> Assertions.assertEquals(expected.getDisposition(),
attachment == null ? null : attachment.getDisposition(),
prefix + " disposition should be '" + expected.getDisposition() + "'"));
registry.register(() -> Assertions.assertArrayEquals(expected.getContent(),
attachment == null ? null : getContent(attachment),
prefix + " has invalid content"));
} catch(Exception e) {
throw new MessageReadingException("Failed to make assertions on attachment", e);
}
// @formatter:on
}
@SuppressWarnings("squid:S2147") // false positive: merging exception
// doesn't compile in that case or we
// are force to throw Exception instead
// of MessagingException
private static BodyPart getAttachmentOrNull(Multipart multipart, final String filename, AssertionRegistry registry) throws MessageReadingException {
try {
return getAttachment(multipart, filename);
} catch (MessagingException e) {
registerAndWrap(registry, e, (ex) -> new MessageReadingException("Failed to get attachment "+filename, ex));
return null;
} catch (IllegalStateException e) {
registry.register(failure(e));
return null;
}
}
private static <E extends Exception> Executable<E> failure(E exception) {
return () -> {
throw exception;
};
}
private static <E extends Exception> void registerAndWrap(AssertionRegistry registry, E originalException, Function<Exception, MessageReadingException> wrapper) throws MessageReadingException {
try {
registry.register(failure(originalException));
} catch (Exception e) {
throw wrapper.apply(e);
}
}
private AssertAttachment() {
super();
}
}