2011-09-09 27 views
4

我真的感觉不好。单元测试,发送电子邮件,并创建一个新的线程

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

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

MailMessage email = new MailMessage(); 

     email.To.Add("[email protected]"); 

     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并调用无tifyMembers与一些数据,代码将抛出一个异常,但只有当我在一个分离的线程执行。

我创建的线程设置在foregronnd,所以系统不会销毁我想要的过程。

异常消息是这样的:

SmtpException:无法评估表达式,因为代码被优化或天然帧是在调用堆栈的顶部

我走至2点内的异常,我看到这

_message“线程正在中止。”字符串

为什么会发生这种情况? 是什么导致线程中止?

+0

这是测试包括任何UI层组件的调用?有时它值得在测试程序集配置中指定MTA公寓状态 – sll

+0

服务创建一个新线程,因为我不想阻塞主线程。这个线程(创建deamon的线程)将继续,并返回到将呈现视图以显示给客户端的MVC应用程序。 – anotherNeo

+0

因此,我认为是UI级别,您是否尝试使用我提供的代码段来更改AppartmentState for NUNit线程? – sll

回答

2

更改您的单元测试,采取IMailService或类似的依赖项。那么你的web应用程序单元测试不需要做任何事情real在发送电子邮件方面 - 它可以使用假的或模拟的。

然后你需要创建一个生产实施IMailService当然 - 和单元测试仍可能是一项挑战,但至少你会那么是测试邮件处理,这意味着你可能有兴趣能够在一定程度上改变约束。

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

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> 
相关问题