Поскольку вы не хотите внедрять SmtpClient
, используя внедрение зависимостей , вы можете пойти ужасным путем и добавить внутренний конструктор и делегировать CustomSmtpMailer
, чтобы помочьв издевательствах и испытаниях. Пожалуйста, имейте в виду, что этот подход не очень чистый. Это приведет к наличию кода, предназначенного исключительно для тестирования в сборке вашего продукта, что, как правило, не очень хорошая идея.
Однако это решает вашу проблему, как описано, и помогает вам использовать внедрение зависимостей .
public class CustomSmtpMailer : SmtpClient {
internal delegate void SendInternal(MailMessage message);
private SendInternal _sendAction;
// make sure all your constructors call this one.
// this will make the call to base.Send(MailMessage) the default behaviour.
public CustomSmtpMailer() {
_sendAction = delegate (MailMessage message) { Send(message); };
}
// customizes the SendMail(MailMessage) behaviour for testing purposes.
internal CustomSmtpMailer(SendInternal sendAction) {
_sendAction = sendAction;
}
private void SendMail(MailMessage mailMessage) {
//DoSomeStuff
_sendAction(mailMessage);
}
}
Сделайте внутренних участников видимыми для вашего тестового проекта, добавив это в AssemblyInfo.cs
в вашем проекте.
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("My.Test.Assembly.Name")]
В своем модульном тесте вы можете использоватьвнутренний конструктор для настройки базового вызова.
[Fact]
public void SendMail() {
CustomSmtpMailer service = new CustomSmtpMailer(delegate (MailMessage message) {
Console.WriteLine("I'm a custom Action that can be used for testing");
});
MailMessage mailMessage = new MailMessage();
// Find on web but not available :(
Mock.Arrange(() => new SmtpClient().Send()).Returns(null).IgnoreInstance();
service.SendMail(mailMessage);
}