use*_*661 6 c# events unit-testing asynchronous
我正在尝试从单元测试中单独测试事件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);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我手动插入这样的延迟,则此测试失败...
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后测试通过.
让方法等待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);
Run Code Online (Sandbox Code Playgroud)