代码之家  ›  专栏  ›  技术社区  ›  TomDane

单元测试Episerver-如何将块添加到测试项目中的内容区域

  •  2
  • TomDane  · 技术社区  · 7 年前

    我们想对Episerver验证器进行单元测试,以确保内容区域内没有两个块:

    public class LandingPageValidator : IValidate
    {
        public IEnumerable Validate(LandingPageDataModel instance)
        {
            if (instance.HeroBlock.Count > 1)
            {
                return new ValidationError[]
                {
                    new ValidationError()
                    {
                        PropertyName = "Hero Block",
                        ErrorMessage = "Can only have one Hero Block"
                    }};
            }
    
            return Enumerable.Empty();
        }
    }
    

    我们面临的问题是:在测试项目内部,如何通过编程向内容区域添加第二个块?

    我们尝试过这种方法: EpiServer - Add block to a content area programmatically 但这似乎只在主应用程序中有效(ContentReference.GlobalBlockFooter在测试项目中为null)。

    如果有帮助,下面是数据模型。

    public class LandingPageDataModel : BasePageDataModel
    {
        [Display(
            Name = "Hero block",
            Description = "",
            Order = 140,
            GroupName = SystemTabNames.Content)]
        [AllowedTypes(new[] { typeof(LandingPageHeroDataModel) })]
        public virtual ContentArea HeroBlock { get; set; }
    }
    

    以下是我们尝试过的:

        [Fact]
        public void Validate_WhenHasMoreThanOneHeroBlock_ReturnsError()
        {
            // Arrange
            var validator = new LandingPageValidator();
            var model = new LandingPageDataModel { HeroBlock = new ContentArea()};
            var item = new ContentAreaItem();
            model.HeroBlock.Items.Add(item);
            var expected = new ValidationError[]
                {
                    new ValidationError()
                    {
                        PropertyName = "Hero Block",
                        ErrorMessage = "Can only have one Hero Block"
                    }};
    
            // Act
            var result = validator.Validate(model);
    
            // Assert
            Assert.Equal(expected, result);
        }
    

    然而,当我们尝试将ContentAreaItem添加到ContentArea时(使用model.HeroBlock.Items.add),它抛出了一个空引用异常。确切的错误是:

    System.NullReferenceException
    
    Object reference not set to an instance of an object.
    at EPiServer.Core.ContentArea.AddContentAreaItemsToFragments(IList items, Int32 startIndex)
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   JOSEFtw    7 年前

    你可以使用 NSubstitute 。 我不知道您是否也需要设置ContentLoader,但我已经包含了一些这样做的代码。 但我想你只要 NSU替代 .Returns

    如果只是要设置Count属性,只需使用 contentArea.Count.Returns(items.Count);

    public class ContentAreaTests
    {
        private readonly IContentLoader _contentLoader;
        private ContentReference _contentReferenceOne;
        private ContentReference _contentReferenceTwo;
    
        public ContentAreaTests()
        {
            this.contentLoader = Substitute.For<IContentLoader>();
        }
    
        [Fact]
        public void MyTest()
        {
            this._contentReferenceOne = new ContentReference(1000);
            this._contentReferenceTwo = new ContentReference(2000);
            var contentArea = CreateContentArea(new List<ContentReference>
            {
                this._contentReferenceOne,
                this._contentReferenceTwo
            });
            SetupContentLoader(this._contentLoader);
            var validator = new LandingPageValidator();
            var model = new LandingPageDataModel { HeroBlock = contentArea};
            var expected = new ValidationError[]
            {
                new ValidationError()
                {
                    PropertyName = "Hero Block",
                    ErrorMessage = "Can only have one Hero Block"
                }
            };
    
            // Act
            var result = validator.Validate(model);
    
            // Assert
            Assert.Equal(expected, result);
        }
    
        private void SetupContentLoader(IContentLoader contentLoader)
        {
            contentLoader.Get<ContentData>(this._contentReferenceOne)
                .Returns(new MyBlock
                {
                    Name = "My name"
                });
            contentLoader.Get<ContentData>(this._contentReferenceTwo)
                .Returns(new MyBlock
                {
                    Name = "My name2"
                });
        }
    
        private static ContentArea CreateContentArea(IEnumerable<ContentReference> content)
        {
            var contentArea = Substitute.For<ContentArea>();
            var items = content.Select(x => new ContentAreaItem
            {
                ContentLink = x
            }).ToList();
    
            contentArea.Items.Returns(items);
            contentArea.Count.Returns(items.Count);
    
            return contentArea;
        }
    }