Marwan Tushyeh
Marwan Tushyeh

Reputation: 1525

Writing unit tests for open systems such as Email or SMS senders in C#

i would like to write unit tests for Email and SMS senders that i have in my project, ofcourse since they are open systems i can't test their functionalities from end to end. So i'm looking for a smart way test them.

Below is the code i am using to send email and SMS:

Email:

    public void Send(MailMessage msg)
    {
        SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
        client.EnableSsl = true;
        client.DeliveryMethod = SmtpDeliveryMethod.Network;
        client.Credentials = new NetworkCredential(emailSetting.EmailUser
        , emailSetting.EmailPass);
        client.Send(msg);
    }

SMS :

   public void SendSMS( String toNumber, String message)
    {
         if (client != null)
            client.SendSmsMessage(smsSetting.SMS_Num, toNumber, message);
    }

Upvotes: 1

Views: 1128

Answers (3)

Tony Hopkinson
Tony Hopkinson

Reputation: 20320

This is a classic for a dependency injection solution and mocking.

Write your code as though you could be using anyone of a number of SMS solutions.

Create an Interface say ISMS with a method say Send(recipient, message);

Then implement it in your code that directly calls the sms stuff.

Them when you hahve something that need sms functionality, you instantiate the implementation you want to use and pass it to that code. Now it doesn't care what does the SMS and how.

Have a look at the service locator pattern for a good way to do this.

When it comes to unit testing, you can then create a mock class that implements the interface and inject that. It doesn't send an sms, it might check that recipient and message are valid though, but it doesn't spam your entire team with test data.

Testing that your sms implementation work then done separately, as it doesn't care why , when or what mesage is being sent.

If you wanted to do an end to end test, then that would be an integration test not a unit test, as there's much more than a unit involved.

Upvotes: 0

user1968030
user1968030

Reputation:

for sms 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("[email protected]", "[email protected]","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

Upvotes: 1

bas
bas

Reputation: 14912

The problem with that is that if you are really going for unit-tests then you'd want to mock the mail/sms client.

If you want to actual send emails (which will result in spam if they are ran overnight / during development cycle) then they don't classify as unit-tests, but integration tests.

As a mocking example:

 public class EmailThingy
 {
     private readonly IEmailClient _client;

     public EmailThingy(IEmailClient client)
     {
          _client = client;
     }

     public void Send()
     {
          // do stuff with client
     }
 }

In your unit test

    [Test]
    public void SendEmail()
    {
        var clientMock = MockRepository.GenerateMock<IEmailClient>();

        // define behaviour for clientmock

        var sut = new EmailThingy(clientMock);
        sut.SendMail();
    }

Upvotes: 3

Related Questions