我的单元测试是否足够?

时间:2009-05-06 20:39:46

标签: .net unit-testing email mocking

我正在查看我为电子邮件服务(使用SMTP)编写的单元测试,我想知道一项测试是否足够。这是我的电子邮件服务的片段:

[PluginFamily("EmailService")]
public interface IEmailService
{
    Boolean SendEmail( string toAddress, string fromAddress, string bccAddress,  string ccAddress, string subject,
                       string body, bool html );
}
[Pluggable("EmailService")]
public class EmailService : IEmailService
{
    private IConfigurationReader _configReader;
    public EmailService(IConfigurationReader configurationReader)
    {
        _configReader = configurationReader;
    }
    public bool SendEmail( string toAddress, string fromAddress, string bccAddress, string ccAddress, string subject, string body, bool isHtml )
    {
        MailMessage email = new MailMessage();

        try
        {
            if (_configReader.TestMode)
            {
                toAddress = _configReader.TestEmailAddress;
            }
        }

        //send email here
     }
}

我正在嘲笑IConfigurationReader(基本上是ConfigurationManager的包装器)并将测试模式设置为true,以便测试我是否可以在“测试模式”下发送电子邮件。所以我的单元测试看起来像这样(这是我对该方法的单元测试之一。我有100%的代码覆盖率):

    [Test]
    public void Validate_Send_Email_In_Test_Mode()
    {
        bool result;
        MockRepository mockRepository = new MockRepository();
        var mockConfigReader = mockRepository.StrictMock<IConfigurationReader>();


        using (mockRepository.Record())
        {

            SetupResult.For(mockConfigReader.TestMode).Return(true);
            SetupResult.For(mockConfigReader.TestEmailAddress).Return("test@test.com");
            SetupResult.For(mockConfigReader.EmailContentLocation).Return("test");
            SetupResult.For( mockConfigReader.SmtpHost ).Return( "test.mail.com" );
        }

        ObjectFactory.InjectStub(typeof(IConfigurationReader), mockConfigReader);
        emailService = ObjectFactory.GetInstance<IEmailService>();

        using (mockRepository.Playback())
        {
            result = emailService.SendEmail( "testemail@test.com",
                                                  "test@test.com", "", "",
                                                  "this is a unit test - config in test mode", "body of unit test", true );

        }

        Assert.That( result, Is.True );
        ObjectFactory.ResetDefaults();

    }

这足以进行单元测试吗?我该怎么做才能改善它?

我担心只检查我的方法返回true是不够的单元测试。

4 个答案:

答案 0 :(得分:2)

改善code coverage(所有类型)

答案 1 :(得分:2)

我建议您在满足各种可能的错误条件时包含“成功”的否定测试。例如,传入无效的电子邮件地址并验证是否返回了正确的错误代码和/或异常。

您可能还想模拟实际的SMTP服务器。虽然我没有做太多的搜索,但我找到了this SMTP server mock site。我在Java项目的电子邮件插件测试中使用了与此类似的方法。这样你就不在乎它是在“测试模式”还是生产中。唯一的区别是配置中的服务器/端口组合。这样做的另一个好处是确保您不仅仅是测试“测试代码”。

答案 2 :(得分:2)

发送电子邮件失败了吗?如果可以的话,你至少要测试两个案例,而你的单一测试是不够的。

由于你有一个布尔返回值,这会告诉我你期待两个返回代码之一,所以你再也没有测试所有可能性。

更不用说,在发送电子邮件时,返回值是函数结果中最不重要的:电子邮件是否已发送?

答案 3 :(得分:1)

我会说这部分:

    {
        if (_configReader.TestMode)
        {
            toAddress = _configReader.TestEmailAddress;
        }
    }

代码味道。您应该传入脚趾邮件地址,并确保使用您作为方法参数传入的内容调用该服务,并使用模拟确保它已正确发送到电子邮件api。换句话说,模拟电子邮件api,不要将模拟作为测试主体使用。

这可能有助于您尝试以相反的方式编写,首先进行测试,只有在您可以进行编写证明编写它的测试时才会编写生产代码。