1

Apologies - this is a likely duplicate. But I was unable to find a useful answer elsewhere on the site.

Currently working on adding email-sending functions to an application. It's not been done under TDD but we've built the tests as we go along and have good coverage.

My task involves adding an email dispatch to an existing function.

public ActionResult RequestApproval(int? id)
{
    Job job = rep.GetJob(id);
    //widgets

    job.IsApproved = true;
    SaveJob(job);
}

This is done through a static helper class:

public static class EmailHelper
{
    public static void SendEmail(string subject, string body, params string[] to)
    {
         //gubbins
    }
 }

So I'm adding

EmailHelper.SendEmail("Approval", "Please approve a thing", job.UsersWhoCanApprove.Select(a => a.Email).ToArray());

To the RequestApproval function.

I know I can effectively test email delivery functions by fiddling with the config, but I don't want to do that here. In the first instance, it's slow and in the second that test belongs in the test suite for the static class.

You're not allowed to put interfaces on a static class. So how can I refactor this to that I can mock out or bypass the call to the static class?

Bob Tway
  • 9,301
  • 17
  • 80
  • 162
  • 1
    http://stackoverflow.com/questions/5864076/mocking-static-methods – adt Jun 17 '15 at 09:27
  • 2
    Encapsulate the mail functionality behind an interface and programm against the interface. During test mock the interface and for your running system use an instance of the interface that uses the static EmailHelper class – Jehof Jun 17 '15 at 09:28

1 Answers1

5

Just create an interface and an implementation:

public interface IEmailService
{
    void SendEmail(string subject, string body, params string[] to);
}

public class EmailService : IEmailService
{
    public void SendEmail(string subject, string body, params string[] to)
    {
         //gubbins
    }
 }

Then if you program against the interface and for example constructor inject the real implementation, you can easily mock this email service in your tests by using a mocking framework or simply creating a dummy implementation of the email service. Of course, in your real logic, you use the real EmailService implementation.

In fact, you rarely need real static classes in your code (except if you have extension methods and such). It's just more flexible and modular if you inject instances like this and program against interfaces.

L-Four
  • 13,345
  • 9
  • 65
  • 109
  • Was hoping to avoid this as that helper class is used elsewhere. But seeing as no-one else is coming up with any alternatives, I guess I have a days' refactoring before me :) – Bob Tway Jun 17 '15 at 09:51
  • 1
    But worthwhile because it will improve your code and make it more testable :) – L-Four Jun 17 '15 at 09:52