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

时间:2018-03-14 07:46:01

标签: unit-testing episerver

我们希望对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 个答案:

答案 0 :(得分:1)

您可以使用NSubstitute。 我不知道你是否也需要设置ContentLoader,但我已经包含了一些代码。 但我认为只使用NSubstitute.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;
    }
}