2017-09-15 14 views
0

저는 sitecore 개발자이고 "ArticleController"컨트롤러의 인덱스에서 볼 수있는 로직을 테스트하기위한 샘플 Sitecore 헬릭스 유닛 테스트 프로젝트를 만들고 싶습니다) 조치 방법 :Sitecore.Context.Item을 사용하는 GlassController 작업 단위 테스트 방법

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void Test_ArticleController_With_SitecoreItem() 
    { 
     //Arrange 
     var businessLogicFake = new Mock<IArticleBusiness>(); 

     var model = new ArticleViewModel() 
     { 
      ArticleType = "Newsletter", 
      ShowDownloadButton = true 
     }; 

     businessLogicFake.Setup(x => x.FetchPopulatedModel).Returns(model); 
     //How do I also mock the Sitecore.Context.Item and send it into the constructor, if that's the right approach? 

     ArticleController controllerUnderTest = new ArticleController(businessLogicFake.Object); 

     //Act 
     var result = controllerUnderTest.Index(3) as ViewResult; 

     //Assert 
     Assert.IsNotNull(result); 
     Assert.IsNotNull(result.Model); 
    } 
} 

은 기본적으로 내가 언급에 "LinkField"값을 갖는 Sitecore.Context.Item을, (조롱하려는 :

public class ArticleController : GlassController 
{ 
    public override ActionResult Index() 
    { 
     // If a redirect has been configured for this Article, then redirect to new location. 
     if (Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO] != null && !string.IsNullOrEmpty(Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO].Value)) 
     { 
      var link = (LinkField)Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO]; 
      if (link != null) 
      { 
       if (link.IsInternal) 
       { 
        return Redirect(Sitecore.Links.LinkManager.GetItemUrl(link.TargetItem)); 
       } 
       else 
       { 
        return Redirect(link.Url); 
       } 
      } 
     } 

     var model = new ArticleBusiness().FetchPopulatedModel; 

     return View("~/Views/Article/Article.cshtml", model); 
    } 

    //below is alternative code I wrote for mocking and unit testing the logic in above Index() function 
    private readonly IArticleBusiness _businessLogic; 
    public ArticleController(IArticleBusiness businessLogic) 
    { 
     _businessLogic = businessLogic; 
    } 
    public ActionResult Index(int try_businessLogic) 
    { 
     // How do we replicate the logic in the big if-statement in above "override ActionResult Index()" method? 

     var model = _businessLogic.FetchPopulatedModel; 

     return View("~/Views/EmailCampaign/EmailArticle.cshtml", model); 
    } 
} 

이 내 단위 테스트 클래스에있는 것입니다 위에서 "SitecoreFieldIds.WTW_REDIRECT_TO"로), 어떻게 든 컨트롤러로 보내십시오 원래의 "public override ActionResult Index()"메서드에서 big if 문과 동일한 정확한 논리를 수행합니다.

이 모든 작업을 수행하기위한 정확한 코드는 무엇입니까? 감사!

답변

1

Sitecore 용 단위 테스트 프레임 워크 인 Sitecore.FakeDb을 사용하는 것이 좋습니다. 그 모양을 상황에 맞는 항목의 조롱 짧은 단어에 그래서 :

[TestCase] 
public void FooActionResultTest() 
{ 
    // arrange 
    var itemId = ID.NewID; 
    using (var db = new Db 
    { 
     new DbItem("Some Item", itemId) 
     { 
      new DbField(SitecoreFieldIds.WTW_REDIRECT_TO) { Value = "{some-raw-value}" } 
     } 
    }) 
    { 
     // act 
     Sitecore.Context.Item = db.GetItem(itemId); 

     // assert 
     Sitecore.Context.Item[SitecoreFieldIds.WTW_REDIRECT_TO].Should().Be("{some-raw-value}"); 
    } 
} 
1

당신은 어려운 고립에서 테스트 할 수 있도록 정적 클래스 코드/로직을 결합하고 있습니다. 또한 통제 할 수없는 코드를 조롱하려고합니다.

사용자가 제어하는 ​​추상화 뒤에 원하는 기능을 캡슐화하십시오.

public interface IArticleRedirectService { 
    Url CheckUrl(); 
} 

public class ArticleRedirectionService : IArticleRedirectionService { 
    public Url CheckUrl() {    
     if (Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO] != null && 
      !string.IsNullOrEmpty(Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO].Value)) { 
      var link = (LinkField)Sitecore.Context.Item.Fields[SitecoreFieldIds.WTW_REDIRECT_TO]; 
      if (link != null) { 
       if (link.IsInternal) { 
        return Sitecore.Links.LinkManager.GetItemUrl(link.TargetItem); 
       } else { 
        return link.Url; 
       } 
      } 
     } 
     return null; 
    } 
} 

컨트롤러는 생성자 주입을 통한 서비스에 명시 적으로 의존합니다.

public class ArticleController : GlassController {    
    private readonly IArticleBusiness businessLogic; 
    private readonly IArticleRedirectionService redirect; 

    public ArticleController(IArticleBusiness businessLogic, IArticleRedirectionService redirect) { 
     this.businessLogic = businessLogic; 
     this.redirect = redirect; 
    } 

    public ActionResult Index() { 
     // If a redirect has been configured for this Article, 
     // then redirect to new location. 
     var url = redirect.CheckUrl(); 
     if(url != null) { 
      return Redirect(url); 
     } 
     var model = businessLogic.FetchPopulatedModel;  
     return View("~/Views/EmailCampaign/EmailArticle.cshtml", model); 
    } 
} 

이 코드는 이제 Moq 또는 다른 프레임 워크를 사용한 유닛 테스트를 위해 독립적으로 종속성을 모방 할 수있는 유연성을 제공합니다.