发送电子邮件并创建新线程的单元测试

时间:2011-09-09 12:50:50

标签: .net unit-testing exception

我真的很难过。

我有一个发送电子邮件通知的网络应用程序。

这是一个包含发送如下电子邮件的基本方法的类:

 MailMessage email = new MailMessage();

        email.To.Add("xxx@gmail.com");

        email.Subject = "Test";
        email.Body = "t";

        SmtpClient client = new SmtpClient();

        client.Send(email);

但是我有一个名为NotificatorService的服务验证了一些逻辑,因为这只是一个“额外”,这个服务的方法是在一个新的线程中调用的。我的工作是这样的:

public void NotifyMembers(NotificatorClientDTO clientDto) {
if(clientDto == null)
    throw new ArgumentNullException("clientDto");


Thread t = new Thread( 
    () => {
    // go to database, verify business rules, etc...

    // At the end if it is ok, invoke the method that sends a email
}

t.Start()

}

如果我创建一个单元测试来实例化NotificatorService并使用某些数据调用notifyMembers,那么代码将抛出异常但仅当我在一个单独的线程中执行时。

我创建的主题是在foregronnd设置的,所以系统不会破坏我的过程。

异常消息是:

SmtpException:无法计算表达式,因为代码已优化或本机框位于调用堆栈之上

我走到2个内部异常,我看到了这个

_message“线程正在中止。”串

为什么会这样? 导致线程中止的原因是什么?

2 个答案:

答案 0 :(得分:2)

将您的单元测试更改为IMailService或类似的依赖项。然后,您的Web应用程序单元测试不需要在发送电子邮件方面做任何真正的 - 它可以使用假冒或模拟。

然后你需要创建一个IMailService的生产实现 - 并且单元测试 可能仍然具有挑战性,但至少你只能 对测试邮件处理感兴趣,这意味着您可以稍微改变约束。

您可以为线程创建方面做同样的事情。基本上,尝试从您想要测试的真实逻辑中分离出代码的“讨厌的位”(与邮件服务和线程交互)。

答案 1 :(得分:1)

这看起来像是集成测试而非单元测试,正如您在标题中所指定的那样。

尝试将App.config添加到包含以下内容的Tests.Assembly项目中,看看它是否有帮助:(使用ApartmentState=MTA and ApartmentState=STA

<?xml version="1.0" encoding="utf-8"?>

<configuration>
    <configSections>
        <sectionGroup name="NUnit">
            <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
        </sectionGroup>
    </configSections>

    <NUnit>
        <TestRunner>
            <add key="ApartmentState" value="STA" />
        </TestRunner>
    </NUnit>
</configuration>