【问题标题】:Strange exception testing EmailSender奇怪的异常测试 EmailSender
【发布时间】:2019-03-20 14:43:51
【问题描述】:

我刚刚严格按照 MS 说明在 ASP.NET Core 3.0 MVC 应用程序中搭建 Identity UI 的脚手架。如果我运行该项目,它会很好地打开默认主页,并且该页面上的链接响应良好。然而,一个简单的集成测试失败并出现异常。

EmailSender 中的单个方法如下所示:

public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
    using (var client = new SmtpClient())
    using (var msg = new MailMessage())
    {
        msg.From = new MailAddress("system@timekeeper.co.za");
        msg.To.Add(new MailAddress(email));
        msg.Subject = subject;
        msg.IsBodyHtml = true;

        client.UseDefaultCredentials = false;
        client.Credentials = new NetworkCredential("timekeeper@somewhere.com", "something");
        client.Host = "mail.myhost.com";
        client.Port = 25;
        return client.SendMailAsync(msg);
    }
}

我的测试看起来像这样:

[TestMethod]
public async Task Send_Email()
{
    var sender = new EmailSender();

    await sender.SendEmailAsync("somebody@somewhere.net", "Test Mail", "This is a test");

    Assert.IsTrue(true);
}

当我运行测试时它失败并出现以下异常:

Test method TimeKeeper.Tests.Integration.EmailSEnderTests.Send_Email threw exception: 
System.Threading.Tasks.TaskCanceledException: A task was canceled.
    at TimeKeeper.Tests.Integration.EmailSEnderTests.Send_Email() in D:\Dev\RestServices\TimeKeeper.Tests.Integration\EmailSEnderTests.cs:line 15
   at Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.ThreadOperations.ExecuteWithAbortSafety(Action action)

【问题讨论】:

  • 正常运行时会出现同样的异常还是只在集成测试中出现。
  • @Nkosi 我在正常运行时遇到同样的异常,即当我尝试注册并尝试发送电子邮件时。
  • await 任务而不是返回它。客户可能在有机会完成发送电子邮件之前就被处理掉了。 await client.SendMailAsync(msg);
  • 您还应该注意文档中关于使用现在的废弃 SmtpClient进行新开发docs.microsoft.com/en-us/dotnet/api/…的警告
  • 谢谢,@Nkosi。我已经有一段时间没有发送邮件了,所以正在复制一个示例(当时是一个 MS 示例,它不会等待任务。它可以在完成之前处理它是很有意义的。为什么不回答这个问题,很好的机会它是正确的。哇,这对 SmtpClient 被弃用感到惊讶,但他们推荐 MailKit,无论如何我经常使用它,但只是在消息方面。非常高兴将它用于所有事情。

标签: asp.net testing asp.net-core integration-testing


【解决方案1】:

await 任务而不是返回它。

public async Task SendEmailAsync(string email, string subject, string htmlMessage) {
    using (var client = new SmtpClient())
    using (var msg = new MailMessage()) {
        msg.From = new MailAddress("system@timekeeper.co.za");
        msg.To.Add(new MailAddress(email));
        msg.Subject = subject;
        msg.IsBodyHtml = true;

        client.UseDefaultCredentials = false;
        client.Credentials = new NetworkCredential("timekeeper@somewhere.com", "something");
        client.Host = "mail.myhost.com";
        client.Port = 25;
        await client.SendMailAsync(msg); //<-- await completion
    }
}

client 有可能在它有机会完成发送电子邮件之前被处置。

您还应该注意文档中关于使用现在过时 SmtpClient 进行新开发的警告。

DE0005:不应使用 SmtpClient

动机

SmtpClient 不支持许多现代协议。它是仅兼容的。它非常适合来自工具的一次性电子邮件,但不是 扩展到协议的现代要求。

推荐

使用 MailKit 或其他库。

【讨论】:

  • 谢谢,原来使用 MailKit 解决了所有问题。我不能只是await,因为IMailSender 方法的实际签名不包括async。只是public Task SendEmailAsync
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多