单元测试:绕过或模拟对静态电子邮件帮助程序的调用

本文关键字:电子邮件 静态 帮助程序 调用 模拟 单元测试 | 更新日期: 2023-09-27 17:56:37

道歉 - 这可能是重复的。但我无法在网站的其他地方找到有用的答案。

目前正在向应用程序添加电子邮件发送功能。它不是在TDD下完成的,但我们已经构建了测试,并且具有良好的覆盖范围。

我的任务涉及向现有函数添加电子邮件调度。

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

这是通过静态帮助程序类完成的:

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

所以我正在添加

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

到请求批准功能。

我知道我可以通过摆弄配置来有效地测试电子邮件传递功能,但我不想在这里这样做。在第一种情况下,它很慢,在第二种情况下,测试属于静态类的测试套件。

不允许将接口放在静态类上。那么我怎样才能重构它,以便我可以模拟或绕过对静态类的调用呢?

单元测试:绕过或模拟对静态电子邮件帮助程序的调用

只需创建一个接口和一个实现:

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
    }
 }

然后,如果您针对接口进行编程,例如构造函数注入了真正的实现,则可以通过使用模拟框架或简单地创建电子邮件服务的虚拟实现,轻松地在测试中模拟此电子邮件服务。当然,在您的实际逻辑中,您使用的是真正的电子邮件服务实现。

事实上,你的代码中很少需要真正的静态类(除非你有扩展方法等)。如果您注入这样的实例并针对接口进行编程,它只会更加灵活和模块化。