2017-11-16 2 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을 사용해야하는 이유 중 하나입니다.

요점은 SendMail()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

관련 문제