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
25
src/Yavsc.Server/Interfaces/ISmtpClient.cs
Normal file
25
src/Yavsc.Server/Interfaces/ISmtpClient.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MimeKit;
|
||||
|
||||
namespace Yavsc.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Yavsc's own SMTP client surface. Narrower than
|
||||
/// <c>MailKit.Net.Smtp.ISmtpClient</c>: only the calls that
|
||||
/// <c>MailSender</c> actually makes. Production wires
|
||||
/// <c>MailKitSmtpClient</c>; tests wire a recording fake.
|
||||
/// </summary>
|
||||
public interface ISmtpClient : IDisposable
|
||||
{
|
||||
int Timeout { get; set; }
|
||||
|
||||
void Connect(string host, int port, MailKit.Security.SecureSocketOptions options);
|
||||
|
||||
void Authenticate(string userName, string password);
|
||||
|
||||
Task SendAsync(MimeMessage message, CancellationToken cancellationToken = default);
|
||||
|
||||
void Disconnect(bool quit);
|
||||
}
|
||||
}
|
||||
13
src/Yavsc.Server/Interfaces/ISmtpClientFactory.cs
Normal file
13
src/Yavsc.Server/Interfaces/ISmtpClientFactory.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
namespace Yavsc.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds fresh <see cref="ISmtpClient"/> instances on demand.
|
||||
/// Per-call construction is required because <c>MailSender</c>
|
||||
/// owns its client with a <c>using</c> block: a singleton or
|
||||
/// scoped client would race across concurrent sends.
|
||||
/// </summary>
|
||||
public interface ISmtpClientFactory
|
||||
{
|
||||
ISmtpClient CreateClient();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue