如何编写单元测试用例并模拟SmtpClient发送邮件

问题描述 投票:0回答:1

我正在为下面的通信服务类编写单元测试用例。我有以下接口通信服务。 我想为 CommunicationService 中存在的 SendMail 方法编写 Nunit 或单元测试,但不发送邮件。 (smtpClient.Send(mailMessage))

public interface ICommunicationService
{
        bool SendMail(string mailSender, IEnumerable<string> recipients, IEnumerable<string> cc, string subject, string mailContent, string senderPass);
 
    }

继承接口的类

public class CommunicationService : ICommunicationService
    {
        private readonly ILogger<CommunicationService> _logger;
        public CommunicationService(
                            ILogger<CommunicationService> logger)
        {
            _logger = logger;
            
        }

此方法使用SmtpClient发送邮件

        public bool SendMail(string mailSender, IEnumerable<string> recipients, IEnumerable<string> cc, string subject, string mailContent, string senderPass)
        {
            MailMessage mailMessage = new MailMessage
            {
                Subject = subject,
                Body = mailContent,
                From = new MailAddress(mailSender, "XXXX"),
                IsBodyHtml = true
            };

            var recipientsList = recipients.ToList();
            if (!recipientsList.Any())
            {
                _logger.LogWarning("Mail not sent, no recipients specified");
            }

            foreach (var address in recipientsList)
            {
                mailMessage.To.Add(address);
            }

            if (cc != null) 
            {
                foreach (string address in cc)
                {
                    mailMessage.CC.Add(address);
                }
            }
            NetworkCredential networkCredential = new NetworkCredential(mailSender, senderPass);


            try
            {
                SmtpClient smtpClient = new SmtpClient
                {
                    Host = "smtp.office365.com",
                    Port = 587,
                    EnableSsl = true,
                    UseDefaultCredentials = false,
                    Credentials = networkCredential,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    Timeout = 20000,

                };
                smtpClient.Send(mailMessage);
                return true;
            }

            catch (Exception exception)
            {

                _logger.LogError(exception.Message, exception);
                return false;
            }
        }
}

在运行单元测试用例时,我遇到了相同的错误。如何模拟 smtpclient.send() 'SMTP 服务器需要安全连接,或者客户端未经过身份验证。服务器响应为:5.7.57 客户端未经过身份验证,无法发送邮件。错误:535 5.7.3 身份验证失败

这是我尝试过的代码。这是单元测试用例

public void SendMail_SuccessfullySendsMail_ReturnsTrue()
        {
             // Arrange
                var mailSender = "[email protected]";
                var recipients = new List<string> { "[email protected]", "[email protected]" };
                var cc = new List<string> { "[email protected]", "[email protected]" };
                var subject = "Test Subject";
                var mailContent = "Test Body";
                var senderPass = "your-password";

                // Create an instance of your MailSender class
                var mailSenderInstance = new CommunicationService(logger.Object);
            
                // Act
                var result = mailSenderInstance.SendMail(mailSender, recipients, cc, subject, mailContent, senderPass);

                // Assert
                Assert.IsTrue(result);

        }

这是编写的单元测试用例,但它不起作用。我从 nunit 测试用例中收到身份验证不成功的消息。

c# asp.net asp.net-core nunit smtpclient
1个回答
0
投票

你可以像这样重写你的类:

public class CommunicationService: ICommunicationService 
{ 
    private readonly ILogger _logger; 
    private readonly SmtpClient _client; 
    public CommunicationService( ILogger logger, SmtpClient client) 
    { 
        _logger = logger;
        _client = client;
    }

     public bool SendMail(string mailSender, IEnumerable recipients, IEnumerable cc, string subject, string mailContent, string senderPass)
     {
          // validation part of the old method here
          
          // use client from constructor
          _client.Send(mailMessage);
     }
 }

测试方法:

public void SendMail_SuccessfullySendsMail_ReturnsTrue()
    {
         // Arrange
            var clientMock = new Mock<SmtpClient>();
            clientMock.Setup(x => x.Send(/*parameters here*/));

            var mailSender = "[email protected]";
            var recipients = new List<string> { "[email protected]", "[email protected]" };
            var cc = new List<string> { "[email protected]", "[email protected]" };
            var subject = "Test Subject";
            var mailContent = "Test Body";
            var senderPass = "your-password";

            // Create an instance of your MailSender class
            var mailSenderInstance = new CommunicationService(logger.Object, smtpClient.Object);
        
            // Act
            var result = mailSenderInstance.SendMail(mailSender, recipients, cc, subject, mailContent, senderPass);

            // Assert
            Assert.IsTrue(result);

    }
 

还有另一个关于模拟 SmtpClient 的线程(可能提供更优雅的解决方案):How to mock/fake SmtpClient in a UnitTest?

© www.soinside.com 2019 - 2024. All rights reserved.