2011-09-09 25 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> 
相關問題