2013-05-01 10 views
3

테스트중인 레거시 프로젝트를 가져 오려고합니다. 코드는 일반적으로 테스트 할 수있는 방식으로 작성되었지만 일부 타사 종속성은 그렇지 않습니다. 나는이 모양이 어떻게 단위 테스트, 뭔가 주위에 내 머리를 정리하려고 해요 :단위 테스트 작업 구성 요소 C#

class InsightEmailJob : NHibernateJob 
{ 
    public IInsightEmailService InsightEmailService { get; set; } 
    public IReportService ReportService { get; set; } 
    public ITemplatedNotifier TemplatedNotifier { get; set; } 
    public string ReplyEmail { get; set; } 
    public string ReplyName { get; set; } 

    public InsightEmailJob(ISession session, 
     ILog log, 
     IInsightEmailService insightEmailService, 
     IReportService reportService, 
     ITemplatedNotifier templatedNotifier, 
     SystemReplyEmailSpec systemReplyEmailSpec) 
     : base(session, log) 
    { 
     InsightEmailService = insightEmailService; 
     ReportService = reportService; 
     TemplatedNotifier = templatedNotifier; 
     ReplyEmail = systemReplyEmailSpec.ReplyEmail; 
     ReplyName = systemReplyEmailSpec.ReplyName; 
    } 

    public int AccountID{ get; set; } 
    private Account mAccount; 

    public Account Account 
    { 
     get 
     { 
      if (this.mAccount == null) 
      { 
       mAccount = this.InsightEmailService.Get<Account>(AccountID); 
      } 
      return mAccount; 
     } 
    } 


    protected override void DoWork(JobExecutionContext context) 
    { 
     var insightEmail = InsightEmailService.FindAndIncrementEmailForAccount(Account); 
     var report = ReportService.LoadMultiReportByName(insightEmail.ReportName); 
     var reportData = ReportService.Execute(report, new ParameterValuesDictionary(Account, DateTime.Now.AddDays(-7), DateTime.Now, 0)); 
     var templateData = new Hashtable {{"data", reportData}, {"account", Account}}; 
     foreach (var u in Account.Users.Where(x => x.Notify)) 
     { 
      TemplatedNotifier.Send(u.UserName, ReplyName, ReplyEmail, insightEmail.TemplateName, templateData); 
     } 
    } 
} 

내가 그러나 나 ', 많은 사람들이 대신 인터페이스의에서 통과 모의 객체 또는 스텁을 사용하는 것이 좋습니다 것이라고 이해 이것이 실제로 얼마나 유익한 지 조금은 혼란 스럽습니다. 이것은 적절한 메소드가 호출되도록 보장하는 것으로 보이는데, 이는 다소 공허감을 느끼게하고, 실제 구현에있어 실제 테스트와도 매우 유사합니다. 궁극적으로 질문은 어떤 가치를 반환하지 않고 단지 당신이 말한 방식대로 구현되었다는 것을 테스트하기 만하면 부작용을 일으키는 방식으로 단위 테스트를 수행합니까?

답변

0

단위 테스트를 수행 할 때 단위 테스트 일뿐입니다. 주어진 외부 종속성 아래에서 유닛이 어떻게되는지를 의미합니다 (예 : 다른 서비스의 메소드를 호출하는 메소드). 따라서 테스트중인 코드가 올바르게 작동하는 경우 외부 종속성의 다양한 조건을 확인해야합니다. 아무것도 돌려주지 않는 방법에 대한

당신이 비웃음 프레임 워크를 사용하는 경우이

  1. 을 확인하기 위해 여러 가지 방법이 있습니다, 당신은 외부 방법이 적절한 콜을하고 있는지 확인하기 위해 확인 사용할 수 있습니다, 예를 MOQ 말할 매개 변수.
  2. 당신은
0

단위 테스트는 당신의 구현이 제대로 작동 증명하기 위해 작성하는 콜백을 사용하여 외부 방법 (MOQ 좋은 콜백 메커니즘을 가지고)에 전달되는 것을 확인할 수 있습니다. 테스트 코드가 너무 복잡해지고 모의하기가 어려워지면 구현 코드가 복잡해지고 이해하기가 더 어려워 질 것입니다.

종속성을 조롱하는 데 너무 많은 작업이 필요하다고 생각하면 디자인을 재고하고 간단한 양식으로 리팩터링해야합니다.

생성자를 살펴보면 너무 많은 작업을 수행하고있는 것으로 볼 수 있습니다. 6 개의 의존성이 있으며 유효한 단위 테스트를 작성하려면이 모든 것을 조롱해야합니다. NHibernate 세션, 일부보고 서비스를 처리하고 전자 메일을 보내야하기 때문에 여기에 충분한 추상화가 없다고 생각합니다.

Repository Pattern은 데이터 액세스 코드를 추상화하는 공통 패턴입니다. 또한 파트를 보내는 전자 메일을 다른 클래스로 이동하고 여기에서 해당 인터페이스를 사용해야합니다.

반환 값이없는 메소드를 모의하기가 매우 쉽습니다. 이 메소드 호출을 조롱하면 클래스가 외부 종속성을 올바르게 사용하고 있음을 증명할 수 있습니다. 매개 변수 값에 대한 어설 션을 작성하고 코드 유효성 검사를 위해 호출 된 횟수를 작성할 수 있습니다.

어쨌든 여기 여기에 또 다른 추상화를 추가 복잡성을 줄일 것입니다 내가 어떻게 볼 수 없습니다 당신이 Moq

insightEmailService.Setup(mock => mock.FindAndIncrementEmailForAccount(It.IsAny<Account>())) 
        .Verifiable(); 
+0

의 방법을 조롱 할 수있는 방법의 예입니다. 전자 메일 보내기 *는 이미 인터페이스를 구현하는 클래스로 추상화되어 있습니다. 이미 인터페이스를 사용하고 있습니다. IInsightEmailService는 InsightEmails를로드하기위한 저장소입니다. 나는 SystemReplyEmailSpec을 알리미에 넣을 수 있었고, 그것은 의존성을 5로 줄 였지만, 나는 승리를 보지 못했다. 왜 다른 클래스를이 곳에 두는 것이 이미있는 코드를 사용하는 것보다 낫겠습니까? –