单元测试 Episerver - 如何将块添加到测试项目中的内容区域
Unit testing Episerver - how to add a block to a content area in the test project
我们想对 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();
}
}
我们面临的问题是:如何在测试项目中以编程方式向内容区域添加第二个块?
我们尝试过这种方法: 但这似乎只在主应用程序中有效(ContentReference.GlobalBlockFooter 在测试项目中为空)。
如果有帮助,这里是数据模型。
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)
您可以使用 NSubstitute
。
我不知道您是否也需要设置 ContentLoader,但我已经包含了一些执行此操作的代码。
但我认为你只需要 NSubstitute
和 .Returns
就可以了
如果您想要设置的只是计数 属性,只需使用 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;
}
}
我们想对 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();
}
}
我们面临的问题是:如何在测试项目中以编程方式向内容区域添加第二个块?
我们尝试过这种方法:
如果有帮助,这里是数据模型。
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)
您可以使用 NSubstitute
。
我不知道您是否也需要设置 ContentLoader,但我已经包含了一些执行此操作的代码。
但我认为你只需要 NSubstitute
和 .Returns
如果您想要设置的只是计数 属性,只需使用 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;
}
}