如何在单元测试中模拟伪造的TreeNode的Parent访问器?

问题描述

使用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个。

  1. 通过使用抽象从TreeNode.Parent获取其值来隔离对TreeNode的使用,然后使用NSubstitute之类的方法(或手动)在测试中创建存根。 / li>
public interface ITreeNodeAccessor
{
    TreeNode GetParent(TreeNode node);
}
  1. 切换到Integration Test

当单元测试基础结构无法处理用例时,我个人采取了这两种方法-我采用的方法取决于我实际要测试的内容。