问题描述
使用Kentico 12 SP,修补程序64-我可以创建伪造的 TreeNode 类型并在大多数字段上设置值,但无法为父级设置返回值>我需要在一种方法上运行测试。
我要测试的方法:
public Dictionary<string,string> GenerateBreadcrumbs(TreeNode treeNode)
{
var breadcrumbs = new Dictionary<string,string>();
if (treeNode != null) {
var revBreadcrumbs = new Dictionary<string,string>();
var thisNode = (treeNode.Parent != null && treeNode.Parent.NodeAliasPath != "/") ? treeNode.Parent : null;
while (thisNode != null) {
revBreadcrumbs.Add(thisNode.DocumentName,thisNode.NodeAliasPath.ToLowerInvariant());
thisNode = (thisNode.Parent != null && thisNode.Parent.NodeAliasPath != "/") ? thisNode.Parent : null;
}
foreach (var item in revBreadcrumbs.Reverse())
{
breadcrumbs.Add(item.Key,item.Value);
}
}
return breadcrumbs;
}
在单元测试中,我可以伪造类型为文件夹
的文档类型DocumentGenerator.RegisterDocumentType<Folder>(Folder.CLASS_NAME);
Fake().DocumentType<Folder>(Folder.CLASS_NAME);
我可以创建实例并在其他属性上设置值,它们可以按预期工作
Folder baseFolder = TreeNode.New<Folder>()
.With(f => f.SetValue("DocumentName",docName))
.With(f => f.SetValue("NodeAliasPath",docPath));
但是,当我尝试设置“父项”的返回值时,当被测试的方法调用时,它将忽略该值。
Folder underFolder= TreeNode.New<Folder>()
.With(f => f.SetValue("Parent",baseFolder));
我尝试使用NSubstitute更改 Parent underFolder.Parent.Returns(baseFolder);
的返回值,但它引发了异常"NSubstitute.Exceptions.CouldNotSetReturnDuetoNoLastCallException : Could not find a call to return from."
。
搜索该错误似乎表明我没有按照NSubstitute的预期来伪造该类,这将是这样的:var mockFolder = Substitute.For<Folder>();
我也尝试了Moq版本,都返回了错误{{1} }表示模拟框架无法读取TreeNode的一个或多个属性。ug。
无论如何,我应该使用其他策略对此进行测试吗?我不想为TreeNode写一个包装器,但似乎我可能必须对此进行测试?
解决方法
我认为单元测试不可能做到这一点。
TreeNode.Parent
不是数据库字段支持的字段/原始值(即使NodeParentID
是),因此使用.SetValue()
不会有任何效果。>
在源代码中,TreeNode.Parent
属性至少进行1个数据库查询(可能是2个),而Kentico单元测试基础结构都不能处理这两个查询。
我的建议是使用2个选项中的1个。
- 通过使用抽象从
TreeNode.Parent
获取其值来隔离对TreeNode
的使用,然后使用NSubstitute
之类的方法(或手动)在测试中创建存根。 / li>
public interface ITreeNodeAccessor
{
TreeNode GetParent(TreeNode node);
}
- 切换到Integration Test。
当单元测试基础结构无法处理用例时,我个人采取了这两种方法-我采用的方法取决于我实际要测试的内容。