2017-09-15 54 views
0

我是一名sitecore開發人員,我想創建一個示例sitecore螺旋單元測試項目來測試您在「ArticleController」控制器的索引中看到的邏輯( )操作方法:如何單元測試使用Sitecore.Context.Item的GlassController動作

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); 
    } 
} 

這是我在我的單元測試類:

[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); 
    } 
} 

基本上我想嘲笑一個Sitecore.Context.Item,其中有一個「LinkField」值(簡稱到上面的「SitecoreFieldIds.WTW_REDIRECT_TO」),以某種方式將它發送到控制器,並在我們最初的「public override ActionResult Index()」方法中執行與大if語句相同的確切邏輯。

做所有這些的確切代碼是什麼?謝謝!

回答

1

我強烈建議您使用Sitecore.FakeDb作爲Sitecore的單元測試框架。因此,在短期的話嘲笑上下文項會看起來像:

[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); 
    } 
} 

代碼現在有彈性,在隔離模擬依賴於單元測試起訂量或任何其他框架。

相關問題