使用邮政和最小起订量进行单元测试邮件发送

Unit-testing mail sending with postal and moq

System.ArgumentNullExceptionSystem.Web.HttpBrowserCapabilities 构造函数中抛出,当 mail.Send() 从测试调用时。它需要 httpBrowserCapabilities 参数。

我用过的代码:

电子邮件模型:

public class EmailModel :Email
{
    public EmailModel() :base("EmailModel")
    {

    }
    public string To = "**********@gmail.com";

    [Display(ResourceType = typeof(Resource), Name = "Name")]
    [Required(ErrorMessageResourceName = "Error_NameRequired", ErrorMessageResourceType = typeof(Resource))]
    public string Name { get; set; }

    [DataType(DataType.EmailAddress)]
    [Display(ResourceType = typeof (Resource), Name = "Email")]
    [Required(ErrorMessageResourceName = "Error_EmailRequired", ErrorMessageResourceType = typeof(Resource))]
    [RegularExpression(".+@.+", ErrorMessageResourceName = "Error_EmailWrong", ErrorMessageResourceType = typeof(Resource))]
    public string Email { get; set; }

    [Display(ResourceType = typeof(Resource), Name = "Topic")]
    [Required(ErrorMessageResourceName = "Error_TopicRequired", ErrorMessageResourceType = typeof(Resource))]
    public string Topic { get; set; }

    [Display(ResourceType = typeof(Resource), Name = "Massage")]
    [DataType(DataType.MultilineText)]
    [Required(ErrorMessageResourceName = "Error_MassageRequired", ErrorMessageResourceType = typeof(Resource))]
    public string Massage { get; set; }
}

留言查看:

@model *******.Models.EmailModel
@{
    Layout = null;
}
To: @Model.To
Subject: @Model.Topic

The massage from @Model.Name @Model.Email
Massage text:
@Model.Massage

单元测试:

public class EmailSetter
{
    public const string DefaultName = "NameTest";
    public const string DefaultEmail = "EmailTest@domaintest.test";
    public const string DefaultTopic = "TopicTest";
    public const string DefaultMassage = "Massage test.";
    public EmailModel GetEmail(string Name = DefaultName, string Topic = DefaultTopic, string Email = DefaultEmail, string Massage = DefaultMassage)
    {
        EmailModel email = new EmailModel();
        email.Name = Name;
        email.Topic = Topic;
        email.Email = Email;
        email.Massage = Massage;
        return email;
    }
}
[TestClass]
public class MailTests
{
    [TestMethod]
    public void MailSendWithRightModel()
    {
        //Arrange
        HomeController controller = new HomeController();
        Mock<EmailModel> email = new Mock<EmailModel>();
        email.Object.Name = EmailSetter.DefaultName;
        email.Object.Email = EmailSetter.DefaultName;
        email.Object.Topic = EmailSetter.DefaultTopic;
        email.Object.Massage = EmailSetter.DefaultMassage;
        //Act
        controller.Contact(email.Object);
        //Assert
        email.Verify(mail => mail.Send());
    }
}

来自测试的控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(EmailModel emailModel)
{
    if(ModelState.IsValid)
    {
        ViewBag.Send = true;
        emailModel.Send();
        ModelState.Clear();
    }
    return View(emailModel);
}

我尝试过的(单元测试方法):

  1. 通过 new BrowserCapabilitiesFactory 创建 new HttpBrowserCapabilities

  2. HttpBrowserCapabilities 创建 new HttpBrowserCapabilitiesWrapper 对象

有什么想法可以让代码不抛出异常吗? (即让当前的 HttpBrowserCapabilitiesWrapper 获得现有的 HttpBrowserCapabilities):)

来源:Postal Unit Testing

When unit testing code that uses Postal, you may want to verify that an email would be sent, without actual sending it.

Postal provides an interface IEmailService and an implementation, EmailService, which actually sends email.

Assuming you use some kind of IoC container, configure it to inject an IEmailService into your controller.

Then use the service to send email objects (instead of calling Email.Send()).

public class HomeController : Controller {

    readonly IEmailService emailService;

    public HomeController(IEmailService emailService) {
        this.emailService = emailService;
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Contact(EmailModel email) {
        if(ModelState.IsValid) {
            emailService.Send(email);
            ViewBag.Send = true;
            ModelState.Clear();
        }
        return View(email);
    }
}

Test this controller by creating a mock of the IEmailService interface.

[TestClass]
public class MailTests {
    [TestMethod]
    public void MailSendWithRightModel() {
        //Arrange
        var mockService = new Mock<IEmailService>();
        var controller = new HomeController(mockService.Object);
        var email = new EmailSetter().GetEmail();

        //Act
        controller.Contact(email);

        //Assert
        mockService.Verify(m => m.Send(email));
    }
}