测试在不发送邮件的情况下发送电子邮件的方法

时间:2010-05-12 19:52:06

标签: c# unit-testing

我有像

这样的方法
public abstract class Base
{
    public void MethodUnderTest();
}

public class ClassUnderTest : Base
{
    public override MethodUnderTest()
    {
        if(condition)
        {
            IMail mail = new Mail() { /* ... */ };
            IMailer mailer = new Mailer() { /* ... */ }

            mailer.Send(mail);
        }
        else
        {
            /* ... */
        }
    }
}

我有这个方法的单元测试,邮件被发送给我自己,所以它并不可怕(比没有测试更好),但我不想发送邮件。

  • 我遇到的问题是我不希望类中的测试特定代码(即if(testMode)返回;而不是发送邮件)
  • 我不太了解DI,但我考虑将模拟IMailer传递给MethodUnderTest,除了它覆盖了基类,并且没有其他派生自Base的类需要一个IMailer对象(我不想强迫实现者) Base在MethodUnderTest中使用不必要的IMailer)

我还能做什么?

(注意:IMail和IMailer是发送电子邮件的外部库的一部分。它是内部编写的,所以我可以根据需要修改它,尽管在这种情况下我看不到需要)

6 个答案:

答案 0 :(得分:7)

使用依赖注入的标准方法是在IMailer的构造函数中需要ClassUnderTests。如果你这样做,你将模拟邮件传递给你的测试,基类不需要知道关于邮件或邮件的任何信息。

如果出于某些原因这是不合需要的(这种情况非常罕见,通常只在你不控制底层类时才有意义),你可以使用setter injection(“属性注入”)。

答案 1 :(得分:2)

答案 2 :(得分:2)

您可以设置一个非常简单的虚假SMTP服务器,该服务器足以验证客户端是否发送了电子邮件。

答案 3 :(得分:1)

我会做这样的事情(考虑到你没有DI框架):

public class ClassUnderTest : Base
{
    private IMail mail;
    private IMailer mailer

    public ClassUnderTest()
    {
        mail = new Mail() { /* ... */ };
        mailer = new Mailer() { /* ... */ }
    }
    public ClassUnderTest(IMail mail, IMailer mailer)
    {
        this.mail = mail;
        this.mailer = mailer;
    }

    public override MethodUnderTest()
    {
        if(condition)
        {
            mailer.Send(mail);
        }
        else
        {
            /* ... */
        }
    }
}

然后在测试中,只需调用第二个构造函数,而不是默认构造函数。

答案 4 :(得分:0)

我的回答一般(我不知道C#)

我曾经需要在Java中制作这样的东西。我做了测试以检查发送端口是否打开然后这意味着它几乎完成了。我强行停止这个过程。

答案 5 :(得分:0)

您可以截取通话以在多个级别发送邮件,但您仍然必须在某处拦截它,或忍受接收电子邮件。

这可能是:

  • 拿出测试电子邮件。

  • 添加一个电子邮件过滤器,用于删除电子邮件或将其存储在其他文件夹中,以免他们打扰您。

  • 将测试电子邮件发送到其他电子邮件地址。将您的服务器设置为仅在收到时删除这些电子邮件(或将其保留14天,如垃圾邮件,以便您可以根据需要进行审核)。

  • 将您的电子邮件服务器替换为虚假的本地服务器

  • 将IMailer的imailer.dll或IMailer实现类替换为整个模​​拟等效项,或者使用一个不能实现完整SendMail行为的程序。

  • 向SendMail()添加基类方法,并在运行单元测试时禁用其在基类中的行为。

  • 在ClassUnderTest中添加一个虚拟的SendMail()方法,然后创建一个派生的类进行单元测试,它只是用模拟的实现覆盖SendMail()。

  • 传入用于调用SendMail的接口/对象

  • 传入一个标记以指示是否正在测试。

  • 完全重新设计类,使其具有SendReport(),并且可以通过电子邮件,TCP / IP,日志文件等发送报告。

当然,最好的方法不需要更改正在测试的实际方法。选择最适合您情况的那个,以及您需要为此课程添加的其他单元测试。