如何对邮件发送功能进行单元测试

时间:2022-01-13 18:13:51

I have a function which creates a report and sends it to a user. What I've done is create a mock for the email function, and verify if the 'send' function of the email class was called.

我有一个创建报告并将其发送给用户的功能。我所做的是为电子邮件功能创建一个模拟器,并验证是否调用了电子邮件类的“发送”功能。

So now I know that the function is called, but how do you unit test the body of the Send() function? How can I prove that the subject and body are correct and an attachment is attached to the email?

所以现在我知道该函数被调用,但是如何对Send()函数的主体进行单元测试呢?如何证明主题和正文是正确的并且附件附在电子邮件中?

6 个解决方案

#1


30  

Can be done in following ways.

可以通过以下方式完成。

Step 1: Navigate to your Web.Config file and add the following tags to it.

步骤1:导航到Web.Config文件并向其添加以下标记。

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

Make sure the directory you have specified for pickup location must exist.

确保您为拾取位置指定的目录必须存在。

Step 2 : Now test your email sending functionality. I have used button_click to test this functionality with the following code.

第2步:现在测试您的电子邮件发送功能。我使用button_click使用以下代码测试此功能。

SmtpClient smtp = new SmtpClient();
MailMessage message = new MailMessage("me@gmail.com", "me@yahoo.com","My Message Subject","This is a test message");
smtp.Send(message);

Output : It will create .eml files inside the folder with a randonly generated GUID name, which is the email that we can see after receiving it. For me it created a file like c127d1d5-255d-4a5a-873c-409e23002eef.eml in E:\MailTest\ folder

输出:它将使用randonly生成的GUID名称在文件夹中创建.eml文件,这是我们收到后可以看到的电子邮件。对我来说,它在E:\ MailTest \文件夹中创建了一个类似c127d1d5-255d-4a5a-873c-409e23002eef.eml的文件

Hope this helps :)

希望这可以帮助 :)

#2


12  

In your unit test tell your mocking framework to expect a call to Send() with a specific body text.

在您的单元测试中,告诉您的模拟框架期望使用特定正文文本调用Send()。

Example for Rhino Mocks:

Rhino Mocks示例:

var mockMail = MockRepository.GenerateMock<Mail>();
mockMail.Expect( m => m.Send("ExpectedFrom", "ExpectedTo", "ExpectedSubject", "ExpectedBodytext") );

mockMail.Send(...whatever...);

mockProvider.VerifyAllExpectations();

#3


8  

I recently ran into this issue myself. Try using http://netdumbster.codeplex.com/. This library allows you to spin up a local SMTP server and check which mails it received. This is all handled in memory AFAIK so the perfomance impact on your test should be minimal.

我最近自己遇到了这个问题。尝试使用http://netdumbster.codeplex.com/。此库允许您启动本地SMTP服务器并检查它收到的邮件。这一切都在内存AFAIK中处理,因此对测试的性能影响应该是最小的。

In your test you create the server like this

在您的测试中,您可以像这样创建服务器

SimpleSmtpServer server = SimpleSmtpServer.Start(25);

Then just change the config of your mail sender class to use the local smtp server (localhost:25). After the mail is send you can access it like this

然后只需更改邮件发件人类的配置即可使用本地smtp服务器(localhost:25)。发送邮件后,您可以像这样访问它

server.ReceivedEmail[0]

And use the Data or MessageParts property to check for subject, body and attachments.

并使用Data或MessageParts属性检查主题,正文和附件。

I hope this helps.

我希望这有帮助。

#4


1  

At least in my case, all email sending is encapsulated in a 'MailService' class - and all send calls go through a send method in the class. The send method is virtual - and all it does is new up an SmtpClient, send the mail, etc. For my unit tests, I have a private class MailServiceMock, that overrides send and does nothing. All of the other methods can be tested - but send is short-circuited.

至少在我的情况下,所有电子邮件发送都封装在“MailService”类中 - 所有发送调用都通过类中的send方法。发送方法是虚拟的 - 它所做的全部是新的SmtpClient,发送邮件等。对于我的单元测试,我有一个私有类MailServiceMock,它覆盖发送并且什么都不做。可以测试所有其他方法 - 但发送是短路的。

oleschri has provided an easier way to do this using Rhino Mocks (I think any mocking framework would work fine) - however if you are hesitant to introduce another dependency, this can get your feet wet with mocking by hand.

oleschri使用Rhino Mocks提供了一种更简单的方法(我认为任何模拟框架都可以正常工作) - 但是如果你对引入另一个依赖项犹豫不决,那么这可能会让你的脚沾满了手工嘲弄。

#5


1  

There is a very simple way to test the email contents in approvaltests (www.approvaltests.com)or nuget)

有一种非常简单的方法可以在批准测试(www.approvaltests.com)或nuget中测试电子邮件内容

The code is simply:

代码很简单:

 EmailApprovals.Verify(mail);

This will create the .eml file, and allow you to view the result in outlook. Future .more, once you approve the result (rename the file to .approved) the test will pass without opening Outlook.

这将创建.eml文件,并允许您在outlook中查看结果。未来。此外,一旦您批准结果(将文件重命名为.approved),测试将通过而无需打开Outlook。

I have created and uploaded a short video on the process to YouTube.

我已经创建了一个关于流程的短视频并将其上传到YouTube。

#6


0  

In the past I have sent real e-mails but I used the decorator pattern on the default EMailGateway implementation.

在过去,我发送了真正的电子邮件,但我在默认的EMailGateway实现中使用了装饰器模式。

So I had an EMailGatewayRedirect that would change the recipient to my own address and, in my case, added a line to the top stating that the e-mail is a test and what the original recipient address was.

所以我有一个EMailGatewayRedirect,可以将收件人更改为我自己的地址,在我的情况下,在顶部添加了一行,说明电子邮件是一个测试,原始收件人地址是什么。

Since I use a DI container I simply instantiated the redirection gateway as my IEMailGateway implementation in my integration tests. In this way a real e-mail was sent.

由于我使用DI容器,我只是在我的集成测试中将重定向网关实例化为我的IEMailGateway实现。通过这种方式发送了一封真正的电子邮件。

#1


30  

Can be done in following ways.

可以通过以下方式完成。

Step 1: Navigate to your Web.Config file and add the following tags to it.

步骤1:导航到Web.Config文件并向其添加以下标记。

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

Make sure the directory you have specified for pickup location must exist.

确保您为拾取位置指定的目录必须存在。

Step 2 : Now test your email sending functionality. I have used button_click to test this functionality with the following code.

第2步:现在测试您的电子邮件发送功能。我使用button_click使用以下代码测试此功能。

SmtpClient smtp = new SmtpClient();
MailMessage message = new MailMessage("me@gmail.com", "me@yahoo.com","My Message Subject","This is a test message");
smtp.Send(message);

Output : It will create .eml files inside the folder with a randonly generated GUID name, which is the email that we can see after receiving it. For me it created a file like c127d1d5-255d-4a5a-873c-409e23002eef.eml in E:\MailTest\ folder

输出:它将使用randonly生成的GUID名称在文件夹中创建.eml文件,这是我们收到后可以看到的电子邮件。对我来说,它在E:\ MailTest \文件夹中创建了一个类似c127d1d5-255d-4a5a-873c-409e23002eef.eml的文件

Hope this helps :)

希望这可以帮助 :)

#2


12  

In your unit test tell your mocking framework to expect a call to Send() with a specific body text.

在您的单元测试中,告诉您的模拟框架期望使用特定正文文本调用Send()。

Example for Rhino Mocks:

Rhino Mocks示例:

var mockMail = MockRepository.GenerateMock<Mail>();
mockMail.Expect( m => m.Send("ExpectedFrom", "ExpectedTo", "ExpectedSubject", "ExpectedBodytext") );

mockMail.Send(...whatever...);

mockProvider.VerifyAllExpectations();

#3


8  

I recently ran into this issue myself. Try using http://netdumbster.codeplex.com/. This library allows you to spin up a local SMTP server and check which mails it received. This is all handled in memory AFAIK so the perfomance impact on your test should be minimal.

我最近自己遇到了这个问题。尝试使用http://netdumbster.codeplex.com/。此库允许您启动本地SMTP服务器并检查它收到的邮件。这一切都在内存AFAIK中处理,因此对测试的性能影响应该是最小的。

In your test you create the server like this

在您的测试中,您可以像这样创建服务器

SimpleSmtpServer server = SimpleSmtpServer.Start(25);

Then just change the config of your mail sender class to use the local smtp server (localhost:25). After the mail is send you can access it like this

然后只需更改邮件发件人类的配置即可使用本地smtp服务器(localhost:25)。发送邮件后,您可以像这样访问它

server.ReceivedEmail[0]

And use the Data or MessageParts property to check for subject, body and attachments.

并使用Data或MessageParts属性检查主题,正文和附件。

I hope this helps.

我希望这有帮助。

#4


1  

At least in my case, all email sending is encapsulated in a 'MailService' class - and all send calls go through a send method in the class. The send method is virtual - and all it does is new up an SmtpClient, send the mail, etc. For my unit tests, I have a private class MailServiceMock, that overrides send and does nothing. All of the other methods can be tested - but send is short-circuited.

至少在我的情况下,所有电子邮件发送都封装在“MailService”类中 - 所有发送调用都通过类中的send方法。发送方法是虚拟的 - 它所做的全部是新的SmtpClient,发送邮件等。对于我的单元测试,我有一个私有类MailServiceMock,它覆盖发送并且什么都不做。可以测试所有其他方法 - 但发送是短路的。

oleschri has provided an easier way to do this using Rhino Mocks (I think any mocking framework would work fine) - however if you are hesitant to introduce another dependency, this can get your feet wet with mocking by hand.

oleschri使用Rhino Mocks提供了一种更简单的方法(我认为任何模拟框架都可以正常工作) - 但是如果你对引入另一个依赖项犹豫不决,那么这可能会让你的脚沾满了手工嘲弄。

#5


1  

There is a very simple way to test the email contents in approvaltests (www.approvaltests.com)or nuget)

有一种非常简单的方法可以在批准测试(www.approvaltests.com)或nuget中测试电子邮件内容

The code is simply:

代码很简单:

 EmailApprovals.Verify(mail);

This will create the .eml file, and allow you to view the result in outlook. Future .more, once you approve the result (rename the file to .approved) the test will pass without opening Outlook.

这将创建.eml文件,并允许您在outlook中查看结果。未来。此外,一旦您批准结果(将文件重命名为.approved),测试将通过而无需打开Outlook。

I have created and uploaded a short video on the process to YouTube.

我已经创建了一个关于流程的短视频并将其上传到YouTube。

#6


0  

In the past I have sent real e-mails but I used the decorator pattern on the default EMailGateway implementation.

在过去,我发送了真正的电子邮件,但我在默认的EMailGateway实现中使用了装饰器模式。

So I had an EMailGatewayRedirect that would change the recipient to my own address and, in my case, added a line to the top stating that the e-mail is a test and what the original recipient address was.

所以我有一个EMailGatewayRedirect,可以将收件人更改为我自己的地址,在我的情况下,在顶部添加了一行,说明电子邮件是一个测试,原始收件人地址是什么。

Since I use a DI container I simply instantiated the redirection gateway as my IEMailGateway implementation in my integration tests. In this way a real e-mail was sent.

由于我使用DI容器,我只是在我的集成测试中将重定向网关实例化为我的IEMailGateway实现。通过这种方式发送了一封真正的电子邮件。