NUnit测试Void功能(发送电子邮件)

时间:2013-08-16 08:45:26

标签: c# asp.net unit-testing nunit

我有一个void函数,它发送电子邮件。我需要为这个函数编写测试。怎么办呢?

public void SendAdminMail(string subject, string body, string adminAddress)
    {

        var email = Email.
            From(ConfigurationManager.AppSettings["Mail.NoReply.Address"].ToString(CultureInfo.InvariantCulture)).
            To(adminAddress).
            Subject(subject).
            Body(body).
            UsingClient(GetOfficeClient());
        email.Message.SubjectEncoding = Encoding.UTF8;
        email.Message.BodyEncoding = Encoding.UTF8;

        email.Send();
    }

5 个答案:

答案 0 :(得分:3)

在这种情况下,这将是非常困难的 - 除非你能够以某种方式通过反思切换Email(正如juhan_h in his answer有趣地指出的那样,现在也许并不那么难;)。 / p>

典型的解决方案是为您的班级提供界面,例如interface EmailFactory。然后你就有了:

private EmailFactory emailFactory;
public void SendAdminMail(string subject, string body, string adminAddress)
{
    var email = emailFactory
        .From(ConfigurationManager
                  .AppSettings["Mail.NoReply.Address"]
                  .ToString(CultureInfo.InvariantCulture))
        .To(adminAddress)
        .Subject(subject)
        .Body(body)
        .UsingClient(GetOfficeClient());

    email.Message.SubjectEncoding = Encoding.UTF8;
    email.Message.BodyEncoding = Encoding.UTF8;

    email.Send();
}

然后你可以为你的班级提供这个工厂的存根,这将创建电子邮件模拟,你可以在其上验证正确的行为。

答案 1 :(得分:2)

如果您碰巧拥有Visual Studio 2012 Ultimate或Premium,那么您可以为System.Net.Mail程序集生成Fakes程序集并使用它。

有关Fakes的更多信息,请访问MSDN

如果您没有VS2012旗舰版或Premium版,那么我的答案是完全没用的。)

答案 2 :(得分:2)

我开始认为在拔下网络电缆时单元测试应该可行。

你真的想测试什么?

您可以使用模拟或伪造,并验证您已按预期调用方法。
能够将这个类存根并在别处使用存根以确保其余的测试在每次运行时都不发送电子邮件可能会更有用。

答案 3 :(得分:1)

  

如何做到这一点?

测试此方法并非直截了当,除非您使用某些库或框架来执行大量变通办法,因为您的方法违反了SRP原则。

虽然您的方法名为SendAmdinMail,但实际上只有一个语句处理发送,为email.Send(),其余方法是使用.NET API构建邮件消息。

您应该将此方法分解为不同的部分,如CreateMailBody,CreateHeader,LoadMailConfig以及隐藏在抽象(接口,抽象类)后面发送的邮件,以便您可以创建邮件发送服务的模拟。 / p>

这样您还可以测试邮件正文的内容,可以测试收件人等。

答案 4 :(得分:1)

您想要写的是integration test而不是unit test

如果你想测试你的代码调用一些负责发送电子邮件的函数,那么你想通过使用某种模拟框架来编写单元测试,例如NSubstitute

[Test]
public void ShouldSendEmail()
{
    IEmailService mockEmailService = Substitute.For<IEmailService>();
    MyEmailSendingThingy thingUnderTest = new MyEmailSendingThingy(mockEmailService);

    thingUnderTest.DoSomeWorkThatInvolvesSendingEmails();

    mockEmailService.Received().SendEmail("foo@foo.foo", "bar@bar.bar", "Subject", "Some Text");
}

如果您想测试您的应用程序实际发送的电子邮件,您想要编写集成测试。您可以通过多种方式实现这一目标。

  1. 编写等待一段时间的测试,然后从测试电子邮件帐户中检索电子邮件,并验证其是否收到了预期的消息。
  2. 将电子邮件发送到内部SMTP服务器,该服务器设置为将电子邮件存储在drop文件夹中,然后可以通过测试代码进行检查。
  3. 模拟SMTP端点并模仿调用SMTP服务器所期望的响应。然后,您可以与您的终端验证它收到了预期的电子邮件。
  4. 使用Moles或Fakes。
  5. 模拟System.Mail组件

    1和2需要付出很多努力,您必须考虑发送电子邮件的异步性质。这意味着您将不得不睡眠您的程序或使用某种触发器等待电子邮件到达目的地,应尽可能避免。

    3我的个人选择有三个原因。您可以在测试过程中托管它,从而更容易进行断言。其次,它是可重用的,可以在任何测试框架中使用。第三,作为奖励,您可以更好地了解电子邮件的工作原理。

    4就个人而言,我不喜欢嘲笑静态或具体的组件..它可能导致坏习惯和糟糕的代码。但是,使用正确方法的工具可能是一件有用的事情,这可能是您测试这部分代码的最佳方式。

    最后确保您正在测试正确的事情。您不应该测试Microsoft是否正确编写了System.Email组件,您只需要确保正确调用组件