【问题标题】:How to Unit Test a GlassController Action which Returns a View Taking a Model如何对 GlassController 操作进行单元测试,该操作返回采用模型的视图
【发布时间】:2017-09-12 22:24:29
【问题描述】:

我是一名站点核心开发人员,我想创建一个示例站点核心螺旋单元测试项目来测试我们的“HomeBottomContentController”控制器:

    public class HomeBottomContentController : GlassController
    {
        private readonly ISitecoreContext _iSitecoreContext;
        public HomeBottomContentController(ISitecoreContext iSitecoreContext)
        {
            _iSitecoreContext = iSitecoreContext;
        }

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

我创建了一个 WTW.Feature.HomeBottomContent.Tests 项目,目的是使用 helix 单元测试来测试整个组件。其中我有一个 UnitTest1.cs 文件,其中包含以下内容:

namespace WTW.Feature.HomeBottomContent.Tests
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void Test_ISitecoreContextInsertion()
        {
            var iSitecoreContext = Mock.Of<Glass.Mapper.Sc.ISitecoreContext>();
            HomeBottomContentController controllerUnderTest = new HomeBottomContentController(iSitecoreContext);
            var result = controllerUnderTest.Index() as ViewResult;
            Assert.IsNotNull(result);
        }
    }
}

这个测试确实通过了,这意味着“结果”不为空;但是,问题是当我进入 Index() 代码时,我看到“模型”变量在我们这样做时为 NULL

    var model = _iSitecoreContext.GetCurrentItem<Home_Control>();

我的问题是,我该如何更改此代码以确保该行中的“模型”不会变为空?如何在 _iSitecoreContext 的单元测试代码中“模拟”一个项目,以便它有一个“Home_Control”模板,其字段的值是合法的?这甚至是正确的方法吗?我发现的大多数在线资源都没有类似的场景,我正在寻找尽可能短的代码。

我遇到的另一个问题是,我如何在 [TestMethod] 中测试下面的 Index() 方法,因为 SitecoreContext 是在 Index() 方法内部声明的,而不是在像上面的 HomeBottomContentController 构造函数?有没有办法从 [TestMethod] 中做到这一点,或者我们必须将 SitecoreContext 作为参数发送到 HomeBottomContentController 构造函数或 Index() 方法中?

public override ActionResult Index()
{
    var context = new SitecoreContext();
    var model = context.GetCurrentItem<Home_Control>();
    return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
}

【问题讨论】:

    标签: c# moq sitecore8 sitecore-mvc glass-mapper


    【解决方案1】:

    在这种情况下,您需要在模拟的依赖项上模拟所需的行为

    [TestClass]
    public class UnitTest1 {
        [TestMethod]
        public void Test_ISitecoreContextInsertion() {
            //Arrange
            var model = new Home_Control() {
                //...populate as needed
            }
            var iSitecoreContext = new Mock<Glass.Mapper.Sc.ISitecoreContext>();
            //Setup the method to return a model when called.
            iSitecoreContext.Setup(_ => _.GetCurrentItem<Home_Control>()).Returns(model);
            var controllerUnderTest = new HomeBottomContentController(iSitecoreContext.Object);
    
            //Act
            var result = controllerUnderTest.Index() as ViewResult;
    
            //Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Model);
            //...other assertions.
        }
    }
    

    更新

    在动作中创建上下文将其与上下文紧密耦合,使其几乎不可能被模拟。这就是注入显式依赖的原因

    【讨论】:

      【解决方案2】:

      你可以这样做:

      public class HomeBottomContentController : GlassController
      {
          private readonly ISitecoreContext _iSitecoreContext;
          public HomeBottomContentController(ISitecoreContext iSitecoreContext)
          {
              _iSitecoreContext = iSitecoreContext;
          }
      
          public override ActionResult Index()
          {
              var model = this.GetCurrentItem();
              return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
          }
      
          protected virtual Home_Control GetCurrentItem() 
          {
              return _iSitecoreContext.GetCurrentItem<Home_Control>();
          }
      }
      
      namespace WTW.Feature.HomeBottomContent.Tests
      {
          [TestClass]
          public class UnitTest1
          {
              [TestMethod]
              public void Test_ISitecoreContextInsertion()
              {       
                  var iSitecoreContext = Mock.Of<Glass.Mapper.Sc.ISitecoreContext>();
                  var controllerUnderTest = new FakeHomeBottomContentController(iSitecoreContext);
                  var result = controllerUnderTest.Index() as ViewResult;
                  Assert.IsNotNull(result);
              }
          }
      
          public class FakeHomeBottomContentController : HomeBottomContentController 
          {
              public FakeHomeBottomContentController(ISitecoreContext iSitecoreContext) : base(iSitecoreContext) 
              {
              }
      
              protected override Home_Control GetCurrentItem()
              {
                  // return instance of Home_Control type
                  // e.g.         
                  return new Home_Control();
              }
          }
      }
      

      【讨论】:

      • 谢谢!另外,鉴于 SitecoreContext 是在 Index() 方法中声明的,而不是像上面那样在 HomeBottomContentController 构造函数中接收,我如何测试下面的 Index()?公共覆盖 ActionResult Index() { var context = new SitecoreContext(); var model = _iSitecoreContext.GetCurrentItem(); return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model); }
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-23
      • 2018-02-25
      • 1970-01-01
      • 2023-04-02
      • 2013-11-25
      • 2011-09-24
      • 2017-05-28
      相关资源
      最近更新 更多