In my application I have an Interface IEmailNotification
that represents an Email and the concrete implementations have nothing to do with MailMessage
class so to be able to send it through SmtpClient
I used an adapter to let the communication between SmtpClient
and IEmailNotification
possible and the job of this adapter is simply delegate the Send call to SmtpClient
but after converting from EmailNotification
to MailMessage
using an abstract Factory which in fact only copying the values from one object to the new created MailMessage
object.
The first question is: my factory method takes a parameter of type IEmailNotification, does that violates the main Job of a Factory which is only creating objects?
public interface INotification
{
string To { get; }
string Body { get; }
}
public interface IEmailNotification : INotification
{
string From { get; }
string Subject { get; }
bool IsBodyHtml { get; }
string CC { get; }
string BCC { get; }
string ReplyToList { get; }
List<string> AttachmentsPaths { get; }
}
public interface IEmailNotificationService : IService
{
void Send(IEmailNotification notification);
}
public class EmailNotificationServiceAdapter : IEmailNotificationService
{
private ISmtpClient _client;
private MailMessageFactory _mailMessageFactory;
public EmailNotificationServiceAdapter(ISmtpClient client, MailMessageFactory mailMessageFactory)
{
_client = client;
_mailMessageFactory = mailMessageFactory;
}
public void Dispose()
{
_client.Dispose();
}
public void Send(IEmailNotification notification)
{
**using (var mailMessage = _mailMessageFactory.CreateMailMessage(notification))**
{
_client.Send(mailMessage);
}
}
}
public class EmailMailMessageFactory : MailMessageFactory
{
public EmailMailMessageFactory(string backupBccEmail)
: base(backupBccEmail)
{
}
public override MailMessage CreateMailMessage(IEmailNotification emailNotification)
{
using (var mailMessage = new MailMessage())
{
mailMessage.From = new MailAddress(emailNotification.From);
mailMessage.To.Add(emailNotification.To);
mailMessage.Subject = emailNotification.Subject;
mailMessage.Body = emailNotification.Body;
if (emailNotification.To.ToLower().Contains("shopfehler"))
mailMessage.Bcc.Add(new MailAddress(_backupBccEmail));
if (!string.IsNullOrEmpty(emailNotification.CC))
mailMessage.CC.Add(emailNotification.CC);
if (!string.IsNullOrEmpty(emailNotification.BCC))
mailMessage.Bcc.Add(emailNotification.BCC);
if (!string.IsNullOrEmpty(emailNotification.ReplyToList))
mailMessage.ReplyToList.Add(emailNotification.ReplyToList);
if (emailNotification.AttachmentsPaths.Count > 0)
{
foreach (var path in emailNotification.AttachmentsPaths)
{
mailMessage.Attachments.Add(new Attachment(path));
}
}
mailMessage.IsBodyHtml = emailNotification.IsBodyHtml;
return mailMessage;
}
}
}
backupBccEmail is required for manipulating the EmailNotification based on some logical conditions
The second question is: When I tried to test the logic of this method It failed because it uses an external resource at the line of adding new attachments where it cannot find the related paths on the Hard Drive, what do you people think about it?
Unit Test Note: I know that only one assert per test is recommended but for now let's keep it simple & straightforward
[TestFixture]
public class EmailMailMessageFactoryTests
{
private EmailNotification _emailNotification;
[SetUp]
public void SetUp()
{
_emailNotification = new EmailNotification("[email protected]", "[email protected];[email protected]", "subject", "body", true)
{
AttachmentsPaths = new List<string> { "1", "2" },
CC = "[email protected]",
BCC = "[email protected]"
};
}
[Test]
public void CreateMailMessage_WhenCalled_CreatesMailMessage()
{
var emailMailMessageFactory = new EmailMailMessageFactory("[email protected]");
var result = emailMailMessageFactory.CreateMailMessage(_emailNotification);
Assert.That(result.From.Address, Is.EqualTo(_emailNotification.From));
Assert.That(result.To[0].Address, Is.EqualTo(_emailNotification.To));
Assert.That(result.Subject, Is.EqualTo(_emailNotification.Subject));
Assert.That(result.Body, Is.EqualTo(_emailNotification.Body));
Assert.That(result.IsBodyHtml, Is.EqualTo(_emailNotification.IsBodyHtml));
Assert.That(result.Attachments.Count, Is.EqualTo(_emailNotification.AttachmentsPaths.Count));
//this assert fails "FileNotFoundException"
Assert.That(result.CC[0].Address, Is.EqualTo(_emailNotification.CC));
Assert.That(result.Bcc[0].Address, Is.EqualTo(_emailNotification.BCC));
}
}
Maybe I'm misusing what's called Factory Pattern in my code!
thanks in advance