2017-11-16 4 views
0

メールを送信せずにBatchProcessに存在するSendMailメソッドのNunitまたはユニットテストを記述したいと思います。ユニットテストのために関数内で使用されるSmtpClientオブジェクトをモックする方法

他の方法の中にあるSmtpClientをモックする方法。助けてください。

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //Assuming we are populating the emails from the data from database 
      List<EmailEntity> emails = new List<EmailEntity>(); 
      BatchProcess.SendMail(emails); 
     } 
    } 

    public class EmailEntity 
    { 
     public string ToAddress { get; set; } 
     public string Subject { get; set; } 
     public string Body { get; set; } 
    } 

    public class BatchProcess 
    { 
     public static void SendMail(List<EmailEntity> emails) 
     { 
      foreach (EmailEntity email in emails) 
      { 
       MailMessage mail = new MailMessage(); 
       SmtpClient SmtpServer = new SmtpClient("sampleSmtp.sampleTest.com"); 
       mail.From = new MailAddress("[email protected]"); 
       mail.To.Add(email.ToAddress); 
       mail.Subject = email.Subject; 
       mail.Body = email.Body; 
       SmtpServer.Port = 587; 
       SmtpServer.Credentials = new System.Net.NetworkCredential("username", "password"); 
       SmtpServer.EnableSsl = true; 
       SmtpServer.Send(mail); 
      } 
     } 
    } 
} 
+1

あなたは、インタフェースISmtpClientの後ろにそれを置くことができます:それはあなたがテストでそれを模擬することができるようにISmtpClientインタフェースを実装SmtpClientの上にラッパーを定義し、BatchProcessのコンストラクタにそのインターフェイスを渡す方が良いでしょう。 – lloyd

+0

あなたのコードは実装に関する懸案事項と緊密に結びついており、これを単独でテストするのは難しいです。柔軟性を高める抽象​​レイヤーが必要です。コメントに記載されているコードを変更/リファクタリングできない場合は、実際のSmtpサービスにヒットする統合テストを実行する必要があります。 – Nkosi

+0

[Typemock Isolator](https://www.typemock.com/docs)を使用することができます。しかし、何を試そうとしていますか? – Sam

答えて

3

これは、Dependency Injectionを使用する理由の1つです。

SmtpClientのインスタンスを作成しないでください。

public interface ISmtpClient 
{ 
    int Port { get; set; } 

    ICredentialsByHost Credentials { get; set; } 

    bool EnableSsl { get; set; } 

    void Send(MailMessage mail); 
} 

public class SmtpClientWrapper : SmtpClient, ISmtpClient 
{ 
} 

public class BatchProcess 
{ 
    private readonly ISmtpClient smtpClient; 

    BatchProcess(ISmtpClient smtpClient) 
    { 
     this.smtpClient = smtpClient; 
    } 

    public void SendMail(List<EmailEntity> emails) 
    { 
     foreach (EmailEntity email in emails) 
     { 
      MailMessage mail = new MailMessage(); 
      mail.From = new MailAddress("[email protected]"); 
      mail.To.Add(email.ToAddress); 
      mail.Subject = email.Subject; 
      mail.Body = email.Body; 

      // You could leave this configuration here but it's far better to have it configured in SmtpClientWrapper constructor 
      // or at least outside the loop 
      smtpClient.Port = 587; 
      smtpClient.Credentials = new System.Net.NetworkCredential("username", "password"); 
      smtpClient.EnableSsl = true; 

      smtpClient.Send(mail); 
     } 
    } 
} 
+0

ご回答いただきありがとうございます。既存のコードを変更することはできません。 SmtpClientを模擬するにはどうすればいいのかを考えてください。 –

+1

適切かつ貴重な単体テストを書くために、生産コードは「テスト可能」でなければなりません。つまり、すべての外部リソースを抽象化する必要があり、適切に分離された単体テストを作成する可能性があります。あなたのケースでは、生産コードを変更するように制限したときに、すべてをモックする機能を持つモッキングフレームワークを使用できます(これらのフレームワークは無料ではありません)。 – Fabio

関連する問題