Enhance MailService: refactor constructor to accept a custom SMTP client factory and add unit tests for SendEmailAsync method
This commit is contained in:
110
FoodsharingSiegen.Tests/MailServiceTests.cs
Normal file
110
FoodsharingSiegen.Tests/MailServiceTests.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FoodsharingSiegen.Contracts.Model;
|
||||
using FoodsharingSiegen.Server.Service;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace FoodsharingSiegen.Tests
|
||||
{
|
||||
public class MailServiceTests
|
||||
{
|
||||
private readonly Mock<IOptions<AppSettings>> _mockOptions;
|
||||
private readonly AppSettings _appSettings;
|
||||
private readonly Mock<ISmtpClient> _mockSmtpClient;
|
||||
|
||||
public MailServiceTests()
|
||||
{
|
||||
_appSettings = new AppSettings
|
||||
{
|
||||
Mail = new MailSettings
|
||||
{
|
||||
Host = "smtp.test.com",
|
||||
Port = 587,
|
||||
UseSsl = false,
|
||||
Username = "user@test.com",
|
||||
Password = "password123",
|
||||
FromAddress = "no-reply@test.com"
|
||||
},
|
||||
Terms = new TermSettings
|
||||
{
|
||||
Title = "Foodsharing Test"
|
||||
}
|
||||
};
|
||||
|
||||
_mockOptions = new Mock<IOptions<AppSettings>>();
|
||||
_mockOptions.Setup(o => o.Value).Returns(_appSettings);
|
||||
|
||||
_mockSmtpClient = new Mock<ISmtpClient>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_ConnectsAuthenticatesAndSendsEmail()
|
||||
{
|
||||
// Arrange
|
||||
var service = new MailService(_mockOptions.Object, () => _mockSmtpClient.Object);
|
||||
var toEmail = "recipient@test.com";
|
||||
var subject = "Test Subject";
|
||||
var body = "<p>Test Body</p>";
|
||||
|
||||
// Act
|
||||
await service.SendEmailAsync(toEmail, subject, body);
|
||||
|
||||
// Assert
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.ConnectAsync(
|
||||
"smtp.test.com",
|
||||
587,
|
||||
SecureSocketOptions.Auto,
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.AuthenticateAsync(
|
||||
"user@test.com",
|
||||
"password123",
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
|
||||
// Verify a MimeMessage is passed to SendAsync with correct attributes
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.SendAsync(
|
||||
It.Is<MimeMessage>(m => m.Subject == subject),
|
||||
It.IsAny<CancellationToken>(),
|
||||
It.IsAny<MailKit.ITransferProgress>()),
|
||||
Times.Once);
|
||||
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.DisconnectAsync(
|
||||
true,
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.Dispose(),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_SkipsAuthentication_WhenUsernameIsBlank()
|
||||
{
|
||||
// Arrange
|
||||
_appSettings.Mail.Username = "";
|
||||
_appSettings.Mail.Password = "";
|
||||
var service = new MailService(_mockOptions.Object, () => _mockSmtpClient.Object);
|
||||
|
||||
// Act
|
||||
await service.SendEmailAsync("recipient@test.com", "Subject", "Body");
|
||||
|
||||
// Assert
|
||||
_mockSmtpClient.Verify(
|
||||
x => x.AuthenticateAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user