在单元测试中等待异步事件引发事件
本文关键字:事件 异步 等待 单元测试 | 更新日期: 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);