How do you unit test a mail sending function
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 c开发者_StackOverflowalled.
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?
Can be done in following ways.
Step 1: Navigate to your Web.Config
file and add the following tags to it.
<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.
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
Hope this helps :)
In your unit test tell your mocking framework to expect a call to Send()
with a specific body text.
Example for Rhino Mocks:
var mockMail = MockRepository.GenerateMock<Mail>();
mockMail.Expect( m => m.Send("ExpectedFrom", "ExpectedTo", "ExpectedSubject", "ExpectedBodytext") );
mockMail.Send(...whatever...);
mockProvider.VerifyAllExpectations();
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.
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
server.ReceivedEmail[0]
And use the Data or MessageParts property to check for subject, body and attachments.
I hope this helps.
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.
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.
There is a very simple way to test the email contents in approvaltests (www.approvaltests.com)or 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.
I have created and uploaded a short video on the process to YouTube.
In the past I have sent real e-mails but I used the decorator pattern on the default EMailGateway implementation.
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.
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.
精彩评论