【发布时间】:2015-08-26 18:50:53
【问题描述】:
我正在尝试对从单元测试中引发的事件 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);
}
}
那么测试通过了。
通过将方法 await smtp.SendAsync 包装为任务似乎并没有真正起作用,因为我实际上并没有等待 SendAsync,我正在尝试等待 SendCompleted 完成执行,然后再继续其余部分测试,我不太确定该怎么做。
出于时间原因,我只等待最少的时间让 SendCompleted 完成处理是非常重要的。
我进行了大量搜索,但似乎找不到任何解决此特定问题的内容。
快速编辑:在所有情况下,电子邮件都成功发送,只有测试失败。
【问题讨论】:
-
你测试
SmtpClient有什么原因吗?这不是您编写的代码,那么测试它的意义何在? -
我不是在测试 SmtpClient,我知道它可以工作。我正在自定义处理程序中测试代码。
-
您应该只在测试中模拟
SmtpClient,这样您的测试就不会依赖于SmtpClient的行为。就像stackoverflow.com/questions/19971364/…中的例子一样。 -
创建 SmtpClient 的传真如何帮助我确定实际 SmtpClient 中的事件时间?我不是在测试事件是否触发,或者 SmtpClient 是否真的做任何事情。我正在测试事件触发的时间。如果在事件触发时我无法牢固锁定,那么我将不得不继续插入一个次优的手动延迟。
-
您的测试不应该在 SmtpClient 的实际时间上进行。你无法控制它——它是框架的一个实现细节。在您的控制之外测试代码没有用。使用模拟 SmtpClient,您可以控制时间(例如立即触发 SendCompleted 事件),因此您可以确保您的 SendComplete 处理程序立即运行。
标签: c# unit-testing events asynchronous