2011-03-09 153 views
20

我想用.NET(C#)框架或任何兼容的库来测试我的电子邮件发送功能,任何建议怎么做?如何对电子邮件发送进行单元测试?

+0

当代码执行时你收到一封电子邮件吗? – 2011-03-09 22:27:38

+0

代码是什么样的? – 2011-03-09 22:30:19

+0

也许你可以显示你正在测试的*功能的代码,你不觉得吗? – 2011-03-09 22:38:15

回答

0

我通常有我设置为我自己的电子邮件的“OverrideEmailAddress”设置,然后运行也不会去你的客户或任何人,他们将原本去任何电子邮件测试。我有一个帮助器方法,我发送所有的电子邮件通过,这种方法将使用该设置,如果它存在。或者,您可以添加到原始收件人的电子邮件底部。

如果需要再确认的电子邮箱收到你就必须编写一些代码来实际检查的电子邮件地址,然后确认该消息是正确的。

不知道这是不是你的意思。

31

如果你需要测试只发送电子邮件,你可以配置你的config文件这样

<system.net> 
    <mailSettings> 
     <smtp deliveryMethod="SpecifiedPickupDirectory"> 
      <specifiedPickupDirectory pickupDirectoryLocation="C:\TempMail" /> 
     </smtp> 
    </mailSettings> 
</system.net> 

通过这些设置你的消息不通过网络发送,但如丢弃在pickupDirectoryLocation属性中配置的文件夹中带有.eml扩展名的物理文件。您可以在System.IO命名空间中的类的帮助下检查它们。

MSDN文档是here

+0

在配置中拥有msdn链接会很好。 – mathk 2014-06-03 12:36:30

17

我的单元测试过程中实际发送电子邮件的概念不以为然。这就要求IMO遇到很多麻烦,并且违背了单元测试应该考虑的内容。

在我的应用程序,我有一个IMailManager接口与像SendPasswordResetEmail(string emailAddress)的方法等。我在单元测试期间嘲笑这个对象,并确保我的组件正在调用正确的邮件管理器方法。

我的实际生产实施MailManager通常在内部使用System.Net.Mail.SmtpClient,您不需要测试。让微软测试一下。所有你需要做的就是确保你的smtp设置在部署时正确设置,这不应该成为单元测试的问题。

如果您需要测试您的邮件组件本身,即确保它生成正确的邮件正文等,我建议嘲笑将此功能隔离为自包含的单元测试所需的内容。

+1

你怎么知道你的SendPasswordResetEmail方法是否正确实现?你没有。这就是为什么你需要测试它。真的,我可能不会称这些单元测试,但他们需要进行测试,无论。 – 2012-03-13 22:09:56

+3

@SleeperSmith这不是一个单元测试,这是一个集成测试,因为它与外部系统进行通信。这种测试是必要的,但不是单元测试能力。 – 2012-06-18 13:56:29

+0

问题是测试实际的'电子邮件发送功能'。我非常确定'单元测试'作者真的想到了一种集成测试。 – whyleee 2012-08-26 01:56:52

0

我可能会写一篇关于.NET SmtpClient类的顶部真的瘦抽象层。然后,我可以用模型类代替单元测试。当然,你将无法单元测试封装,但无论如何它都应该实际上是微不足道的,几乎不会改变。

0

有一个很简单的方法来测试approvaltests电子邮件内容(www.approvaltests.com或的NuGet)。代码很简单:

EmailApprovals.Verify(mail); 

这将创建.eml文件,并允许您在Outlook中查看结果。此外,一旦您批准结果(将文件重命名为“批准”),测试将通过而不打开前景。 (这是一个非常类似的过程@whyleee提到什么,但不使用的配置文件。)

I have published a short video on the process on YouTube

11

您不需要测试实际的电子邮件发送功能;这是.NET框架的一部分,它已经过测试。

你需要单元测试的是电子邮件创建业务逻辑。将其封装在如下服务中:

public interface IPasswordResetEmailCreator 
{ 
    MailMessage Create(string emailAddress); 
} 

并执行它。然后编写一个这个实现的单元测试并验证它返回的邮件消息符合您的要求。

使用SpecsFor框架这个单元测试的样本实施:

public class PasswordResetEmailCreatorSpecs 
{ 
    public class given_a_registered_user : SpecsFor<PasswordResetEmailCreator> 
    { 
     private string _emailAddress; 
     private MailMessage _email; 

     protected override void Given() 
     { 
      _emailAddress = "[email protected]"; 
     } 

     protected override void When() 
     { 
      _email = SUT.Create(_emailAddress); 
     } 

     [Test] 
     public void then_the_body_must_contain_the_reset_uri() 
     { 
      _email.Body.ShouldContain("/Password/Reset/"); 
     } 

     [Test] 
     public void then_the_email_must_be_for_the_user() 
     { 
      _email.To[0].Address.ShouldEqual(_emailAddress); 
     } 

     [Test] 
     public void then_the_subject_must_be_the_expected() 
     { 
      _email.Subject.ShouldEqual("Your email reset link"); 
     } 
    } 
} 
0

如果你想测试它,我会建议看mail4net:www.mail4net.com

这是一个商业产品,但它允许您使用虚假的SMTP服务发送电子邮件,然后查询该假冒。

// Create Mail4Net FakeClient. 
var client = new Mail4Net.Client.FakeClient(); 

// Send email. 
client.Send(from, to, subject, body); 

然后,你就可以查询客户端:

// Count the number of emails sent. 
var count = client.Count(); 

// Get first email. 
var message = client[0]; 
0

我的快速和肮脏的方法是非常相似的top answer by whylee除了它不需要接触任何配置,文件(因为我可能需要您的电子邮件发送代码中不同的单元测试不同的设置)

if (ConfigurationManager.AppSettings["smtpDir"] == null) 
    smtp.DeliveryMethod = SmtpDeliveryMethod.Network; 
else 
{ 
    smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; 
    smtp.PickupDirectoryLocation = ConfigurationManager.AppSettings["smtpDir"]; 
} 

在您的单元测试

ConfigurationManager.AppSettings["smtpDirectory"] = dir; 

//do some testing then change it back 

ConfigurationManager.AppSettings["smtpDirectory"] = null; 

PS。我知道所有的缺点,但以防万一有人需要这个...

相关问题