在单元测试中等待异步事件引发事件

本文关键字:事件 异步 等待 单元测试 | 更新日期: 2023-09-27 18:10:08

我试图对事件SmtpClient的引发进行单元测试。SendCompleted来自单元测试,我遇到了一个恼人的问题,在事件实际触发之前,测试继续处理,在实际到达事件之前终止了应用程序。那么,想象一下下面的代码:

[TestClass]
public class emailTest
{
    public bool sentEmail = false;
    [TestMethod]
    public void sendEmail()
    {
        SmtpClient smtp = new SmtpClient("smtpserver");
        smtp.SendCompleted += delegate(Object sender, System.ComponentModel.AsyncCompletedEventArgs e) { sentEmail = true; };
        MailMessage mm = new MailMessage("from@address.com", "to@address.com", "test subject", "test body");
        smtp.SendAsync(mm, "test");
        Assert.IsTrue(sentEmail);
    }
}

这个测试失败,但是,如果我手动插入延迟,像这样…

[TestClass]
public class emailTest
{
    public bool sentEmail = false;
    [TestMethod]
    public void sendEmail()
    {
        SmtpClient smtp = new SmtpClient("smtpserver");
        smtp.SendCompleted += delegate(Object sender, System.ComponentModel.AsyncCompletedEventArgs e) { sentEmail = true; };
        MailMessage mm = new MailMessage("from@address.com", "to@address.com", "test subject", "test body");
        smtp.SendAsync(mm, "test");
        System.Threading.Thread.Sleep(50000); // Manual Delay
        Assert.IsTrue(sentEmail);
    }
}

则测试通过。

方法等待smtp。SendAsync通过包装它作为一个任务似乎并不实际工作,因为我实际上没有等待SendAsync,我试图等待SendCompleted完成执行之前继续与测试的其余部分,我不太确定如何做到这一点。

由于时间原因,我只等待SendCompleted完成处理的最小时间是非常重要的。

我做了大量的搜索,似乎就是找不到任何解决这个特定问题的东西。

快速编辑:在所有情况下,邮件发送成功,只是测试失败。

在单元测试中等待异步事件引发事件

好吧,我必须承认SendCompleted只在SendAsync返回后才被解雇的事实听起来有点奇怪…它确实使单元测试更加困难。

但是如果您想要等待最少的时间,则必须引入同步原语。AutoResetEvent听起来很适合这个场景。

// Arrange
var are = new AutoResetEvent(false);
var smtp = new SmtpClient("smtpserver");
smtp.SendCompleted += (s, e) => { are.Set(); };
var mm = new MailMessage("from@address.com", "to@address.com", "test subject", "test body");
// Act
smtp.SendAsync(mm, "test");
// Assert
var wasSignaled = are.WaitOne(timeout: TimeSpan.FromSeconds(1));
Assert.True(wasSignaled);