Introduce Yavsc.Interfaces.ISmtpClient and a recording test fake
Narrow ISmtpClient to the four operations MailSender actually uses, behind a Yavsc.Interfaces.ISmtpClientFactory. Production wires MailKitSmtpClient (SmtpClientFactory); tests wire a recording fake (RecordingSmtpClientFactory). The fake is pre-registered in WebServerFixture so SMTP calls are short-circuited; the EMailling test now asserts the Connect -> Authenticate -> Send -> Disconnect sequence. Yavsc.Abstract stays free of MailKit/MimeKit.
This commit is contained in:
parent
16508e9fb2
commit
2dec799d71
13 changed files with 264 additions and 10 deletions
71
src/Yavsc.Org.Tests/Fakes/RecordingSmtpClient.cs
Normal file
71
src/Yavsc.Org.Tests/Fakes/RecordingSmtpClient.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using MailKit.Security;
|
||||
using MimeKit;
|
||||
using Yavsc.Interfaces;
|
||||
|
||||
namespace Yavsc.Org.Tests.Fakes
|
||||
{
|
||||
/// <summary>
|
||||
/// In-memory test double for <see cref="ISmtpClient"/>. Records
|
||||
/// every call for assertion and short-circuits the SMTP
|
||||
/// roundtrip.
|
||||
/// </summary>
|
||||
public sealed class RecordingSmtpClient : ISmtpClient
|
||||
{
|
||||
public List<RecordingSmtpCall> Calls { get; } = new();
|
||||
|
||||
public int Timeout { get; set; }
|
||||
public string? LastConnectedHost { get; private set; }
|
||||
public int LastConnectedPort { get; private set; }
|
||||
public SecureSocketOptions LastConnectedOptions { get; private set; }
|
||||
public string? LastAuthenticatedUser { get; private set; }
|
||||
public MimeMessage? LastSentMessage { get; private set; }
|
||||
public bool WasDisconnected { get; private set; }
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
public void Connect(string host, int port, SecureSocketOptions options)
|
||||
{
|
||||
LastConnectedHost = host;
|
||||
LastConnectedPort = port;
|
||||
LastConnectedOptions = options;
|
||||
Calls.Add(new RecordingSmtpCall(RecordingSmtpCallKind.Connect, host, port, options));
|
||||
}
|
||||
|
||||
public void Authenticate(string userName, string password)
|
||||
{
|
||||
LastAuthenticatedUser = userName;
|
||||
Calls.Add(new RecordingSmtpCall(RecordingSmtpCallKind.Authenticate, userName, null, null));
|
||||
}
|
||||
|
||||
public Task SendAsync(MimeMessage message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastSentMessage = message;
|
||||
Calls.Add(new RecordingSmtpCall(RecordingSmtpCallKind.Send, message.Subject, null, null));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Disconnect(bool quit)
|
||||
{
|
||||
WasDisconnected = quit;
|
||||
Calls.Add(new RecordingSmtpCall(RecordingSmtpCallKind.Disconnect, null, null, null));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RecordingSmtpCallKind
|
||||
{
|
||||
Connect,
|
||||
Authenticate,
|
||||
Send,
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
public readonly record struct RecordingSmtpCall(
|
||||
RecordingSmtpCallKind Kind,
|
||||
string? HostOrSubjectOrUser,
|
||||
int? Port,
|
||||
SecureSocketOptions? Options);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue