【问题标题】:How to Unit Test a GlassController Action without SitecoreContext Dependency Injection如何在没有 SitecoreContext 依赖注入的情况下对 GlassController 操作进行单元测试
【发布时间】:2023-04-02 23:27:01
【问题描述】:

我是一名 sitecore 开发人员,我想创建一个示例 sitecore helix 单元测试项目,用于测试我们的“HomeBottomContentController”控制器的 Index() 操作方法 exact,没有任何依赖注入到构造函数中。请注意,注释掉的代码正是我不想做的。

public class HomeBottomContentController : GlassController
{
    // I want to test the EXACT method below
    public override ActionResult Index()
    {
        var context = new SitecoreContext();
        var model = context.GetCurrentItem<Home_Control>();
        return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
    }

    /*
    // I do NOT want to have any of the below code for injecting ISitecoreContext into a constructor and testing the IndexTest() below it.
    private readonly ISitecoreContext _iSitecoreContext;
    public HomeBottomContentController(ISitecoreContext iSitecoreContext)
    {
        _iSitecoreContext = iSitecoreContext;
    }

    public HomeBottomContentController()
    { }

    public ActionResult IndexTest()
    {
        var model = _iSitecoreContext.GetCurrentItem<Home_Control>();
        return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
    }
    */
}

这是我在单元测试课上的内容。再说一遍,我已经注释掉了我不想想要做的事情:

[TestClass]
public class MvcUnitTests
{
    [TestMethod]
    public void Test_HomeBottomContentController_With_ISitecoreContext()
    {
        /*
        // I don't want to do below...
        var model = new Home_Control()
        { Bottom_Content = "XYZ" };

        var iSitecoreContext = new Mock<Glass.Mapper.Sc.ISitecoreContext>();
        iSitecoreContext.Setup(_ => _.GetCurrentItem<Home_Control>(false, false)).Returns(model);

        HomeBottomContentController controllerUnderTest = new HomeBottomContentController(iSitecoreContext.Object);

        var result = controllerUnderTest.IndexTest() as ViewResult;
        */

        //I want to test using the exact constructor below and calling that exact Index() method.  
        HomeBottomContentController controllerUnderTest = new HomeBottomContentController();
        var result = controllerUnderTest.Index() as ViewResult;
        Assert.IsNotNull(result);
        Assert.IsNotNull(result.Model);
        //Assert.AreEqual(((Home_Control)result.Model).Bottom_Content, "XYZ");
    }
}

如何测试我的控制器的确切 Index() 方法,而无需将代码添加到 HomeBottomContentController 类,该类可以将依赖项注入到构造函数中(如上面注释掉的代码)?我不想向 HomeBottomContentController() 添加代码。

@Aleksey Shevchenko 如果我尝试您的解决方案,我如何将模型准确地连接到 iSitecoreContext,然后将其分配给 controllerUnderTest.FakeContext?我下面的代码抛出编译错误(你不能从 Glass.Mapper.Sc.ISitecoreContext 的 Mock 转换为 Glass.Mapper.Sc.ISitecoreContext,我们如何实现):

var model = new Home_Control()
{ Top_Content = "Some Dummy Test Home Top Content" };
var iSitecoreContext = new Mock<Glass.Mapper.Sc.ISitecoreContext>();
//var iSitecoreContext = new Glass.Mapper.Sc.SitecoreContext();       
iSitecoreContext.Setup(_ => _.GetCurrentItem<Home_Control>(false, false)).Returns(model);
FakeHomeTopContentController controllerUnderTest = new FakeHomeTopContentController();
controllerUnderTest.FakeContext = (Glass.Mapper.Sc.SitecoreContext)iSitecoreContext;

【问题讨论】:

    标签: c# unit-testing dependency-injection sitecore-mvc glass-mapper


    【解决方案1】:

    如果您不想通过构造函数创建依赖注入,您可以通过受保护的虚拟方法来实现。类似的东西:

    public class HomeBottomContentController : GlassController
    {
        public override ActionResult Index()
        {
            var context = this.GetContext();
            var model = context.GetCurrentItem<Home_Control>();
            return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
        }
    
        protected virtual SitecoreContext GetContext() 
        {
            return new SitecoreContext();
        }
    }
    
    [TestClass]
    public class MvcUnitTests
    {
        [TestMethod]
        public void Test_HomeBottomContentController_With_ISitecoreContext()
        {     
            var controllerUnderTest = new FakeHomeBottomContentController();
            controllerUnderTest.FakeContext = /* set what you want */;
            var result = controllerUnderTest.Index() as ViewResult;
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Model);        
        }
    
        public class FakeHomeBottomContentController : HomeBottomContentController 
        {
            public SitecoreContext FakeContext { get; set; }
    
            protected override SitecoreContext GetContext()
            {
                return this.FakeContext;
            }
        }   
    }
    

    【讨论】:

    • 谢谢!这是我所拥有的,它给出了错误,我如何将模型连接到 iSitecoreContext 并将其设置为 FakeContext?: var model = new Home_Control() { Top_Content = "Some Dummy Test Home Top Content" }; var iSitecoreContext = new Mock(); iSitecoreContext.Setup(_ => _.GetCurrentItem(false, false)).Returns(model); FakeHomeTopContentController controllerUnderTest = new FakeHomeTopContentController(); controllerUnderTest.FakeContext = (Glass.Mapper.Sc.SitecoreContext)iSitecoreContext;
    • @user3034243 尝试将最后一行更改为这样的视图:controllerUnderTest.FakeContext = (Glass.Mapper.Sc.SitecoreContext)(iSitecoreContext.Object);
    【解决方案2】:

    我不知道您结束源代码的能力的局限性,但根据您对其他答案的评论,您可以访问它。我会选择Poor Man's DI,控制器上有两个构造函数。单元测试使用第二个构造函数,MVC 将使用无参数构造函数。

    public class HomeBottomContentController : GlassController
    {
    
    ISitecoreContext _iSitecoreContext;
    
    public HomeBottomContentController() :this(new SitecoreContext()){
    }
    
    
    public HomeBottomContentController(ISitecoreContext iSitecoreContext)
    {
        _iSitecoreContext = iSitecoreContext;
    }
    
    
    
    public ActionResult IndexTest()
    {
        var model = _iSitecoreContext.GetCurrentItem<Home_Control>();
        return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
    }
    
    }
    
    [TestClass]
    public class MvcUnitTests
    {
    [TestMethod]
    public void Test_HomeBottomContentController_With_ISitecoreContext()
    {
    
        var model = new Home_Control()
        { Bottom_Content = "XYZ" };
    
        var iSitecoreContext = new Mock<Glass.Mapper.Sc.ISitecoreContext>();
        iSitecoreContext.Setup(_ => _.GetCurrentItem<Home_Control>(false, false)).Returns(model);
    
        HomeBottomContentController controllerUnderTest = new HomeBottomContentController(iSitecoreContext.Object);
    
        var result = controllerUnderTest.IndexTest() as ViewResult;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-08
      • 1970-01-01
      • 2014-07-29
      相关资源
      最近更新 更多