Подтвердить что ты не робот

Как отправить unit test по электронной почте?

Я хотел бы протестировать свои функции отправки электронной почты, используя платформу .NET(С#) или любую совместимую библиотеку, любое предложение, как это сделать?

4b9b3361

Ответ 1

Если вам нужна проверка только отправки электронной почты, вы можете настроить свой файл .config следующим образом

<system.net>
    <mailSettings>
        <smtp deliveryMethod="SpecifiedPickupDirectory">
            <specifiedPickupDirectory pickupDirectoryLocation="C:\TempMail" />
        </smtp>
    </mailSettings>
</system.net>

С этими настройками ваши сообщения не отправляются по сети, а удаляются как физические файлы с расширением .eml в папке, настроенной в атрибуте pickupDirectoryLocation. Вы можете проверить их с помощью классов в пространстве имен System.IO.

Документация MSDN здесь

Ответ 2

Я не согласен с идеей отправки электронной почты во время модульного тестирования. Это требует много проблем с ИМО и идет вразрез с тем, что предполагает модульное тестирование.

В моем приложении у меня есть интерфейс IMailManager с такими методами, как SendPasswordResetEmail(string emailAddress) и тому подобное. Я издеваюсь над этим объектом во время модульного тестирования и просто проверяю, чтобы мои компоненты вызывали правильный метод почтового менеджера.

Моя фактическая производственная реализация MailManager обычно использует System.Net.Mail.SmtpClient внутренне, что вам не нужно тестировать. Пусть Microsoft проверит это. Все, что вам нужно сделать, это убедиться, что настройки smtp настроены правильно при развертывании, что не должно вызывать проблем при тестировании устройств.

Если вам нужно протестировать свой почтовый компонент, то есть убедиться, что он генерирует правильный текст сообщения и т.п., я бы рекомендовал высмеять то, что необходимо, чтобы изолировать эту функциональность в автономном unit test.

Ответ 3

Вам не нужно проверять фактическую функцию отправки электронной почты; эту часть платформы .NET и она уже протестирована.

Что вам нужно для unit test - это бизнес-логика создания электронной почты. Инкапсулируйте его в таком сервисе:

public interface IPasswordResetEmailCreator
{
    MailMessage Create(string emailAddress);
}

И реализовать его. Затем напишите unit test для этой реализации и убедитесь, что возвращаемое MailMessage соответствует вашим требованиям.

Пример реализации этого unit test с помощью SpecsFor:

public class PasswordResetEmailCreatorSpecs
{
    public class given_a_registered_user : SpecsFor<PasswordResetEmailCreator>
    {
        private string _emailAddress;
        private MailMessage _email;

        protected override void Given()
        {
            _emailAddress = "[email protected]";
        }

        protected override void When()
        {
            _email = SUT.Create(_emailAddress);
        }

        [Test]
        public void then_the_body_must_contain_the_reset_uri()
        {
            _email.Body.ShouldContain("/Password/Reset/");
        }

        [Test]
        public void then_the_email_must_be_for_the_user()
        {
            _email.To[0].Address.ShouldEqual(_emailAddress);
        }

        [Test]
        public void then_the_subject_must_be_the_expected()
        {
            _email.Subject.ShouldEqual("Your email reset link");
        }
    }
}

Ответ 4

У меня обычно есть параметр "OverrideEmailAddress", который я установил в свой собственный адрес электронной почты, а затем все ваши тесты электронной почты, которые вы запускаете, не будут отправляться на ваш клиент или на кого бы они ни отправились. У меня есть вспомогательный метод, по которому я отправляю все электронные письма, и этот метод будет использовать параметр, если он существует. При желании вы можете добавить к нижней части сообщения электронной почты, которым был бы оригинальный получатель.

Если вам нужно подтвердить, что письмо было получено, вам нужно будет написать код для фактического проверки адреса электронной почты, а затем подтвердить правильность сообщения.

Не уверен, что это то, что вы имеете в виду или нет.

Ответ 5

Я бы, вероятно, написал действительно тонкий слой абстракции поверх класса .NET SmtpClient. Затем я мог бы заменить класс макета для модульных тестов. Конечно, вы не сможете unit test обертки, но в любом случае она должна быть практически тривиальной и вряд ли изменится.

Ответ 6

Существует очень простой способ проверить содержимое электронной почты в тестах утверждения (www.approvaltests.com или nuget). Код просто:

EmailApprovals.Verify(mail);

Это создаст файл .eml и позволит вам просмотреть результат в Outlook. Кроме того, как только вы одобряете результат (переименуйте файл в .approved), тест пройдет без открытия перспективы. (Это очень похоже на то, о чем упоминалось @whyleee, но не использует файл конфигурации.)

Я опубликовал короткое видео о процессе на YouTube.

Ответ 7

Если вы хотите протестировать его, я бы рекомендовал посмотреть на mail4net: www.mail4net.com

Это коммерческий продукт, но он позволяет отправлять электронную почту с использованием поддельной службы SMTP и затем запрашивать подделку.

// Create Mail4Net FakeClient.
var client = new Mail4Net.Client.FakeClient();

// Send email.
client.Send(from, to, subject, body);

И затем вы можете запросить клиента:

// Count the number of emails sent.
var count = client.Count();

// Get first email.
var message = client[0];

Ответ 8

Мой быстрый и грязный подход очень похож на верхний ответ whilee, за исключением того, что он не требует касания каких-либо конфигурационных файлов (потому что мне могут потребоваться разные настройки для разных модульных тестов)

внутри вашего кода отправки электронной почты

if (ConfigurationManager.AppSettings["smtpDir"] == null)
    smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
else
{
    smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
    smtp.PickupDirectoryLocation = ConfigurationManager.AppSettings["smtpDir"];
}

В вашем модульном тесте

ConfigurationManager.AppSettings["smtpDirectory"] = dir;

//do some testing then change it back

ConfigurationManager.AppSettings["smtpDirectory"] = null;

PS. Я знаю все минусы, но на всякий случай кому-то это нужно...