你如何对相互递归的方法进行单元测试?

时间:2011-01-19 21:19:35

标签: c# unit-testing recursion

我有三个看起来像这样的函数:

private Node GetNode(Node parentNode)
{
    var node = new node();

    switch (parentNode.NodeType)
    {
       case NodeType.Multiple:    node = GetMultipleNode(parentNode)
       case NodeType.Repeating:   node = GetRepeatingNode(parentNode)
    }

    return node;
}

private Node GetMultipleNode(Node parentNode)
{
    foreach (var child in parentNode.Children)
        return GetNode(child);
}

private Node GetRepeatingNode(Node parentNode)
{
    for (int i=0; i < parentNode.Count; i++)
         return GetNode(new Node(i));  // Assume meaningful constructor for Node
}

鉴于这三种方法是相互递归的,那么如何单独测试它们呢?

3 个答案:

答案 0 :(得分:5)

通常你不需要单独测试每个方法 - 你可以测试顶级方法做正确的事。

但是,如果由于某种原因你希望分别测试每个方法,你可以使用依赖注入,就像测试任何具有依赖关系的方法一样。这里唯一的区别是依赖是对象本身。以下是一些示例代码来演示这个想法:

class NodeGetter : INodeGetter
{
    public Node GetNode(Node parentNode)
    {
        return GetNode(parentNode, this);
    } 

    public Node GetNode(Node parentNode, INodeGetter nodeGetter)
    {
        switch (parentNode.NodeType)
        {
           case NodeType.Multiple:
               return nodeGetter.GetMultipleNode(parentNode, nodeGetter);
           case NodeType.Repeating:
               return nodeGetter.GetRepeatingNode(parentNode, nodeGetter);
           default:
               throw new NotSupportedException(
                   "Node type not supported: " + parentNode.NodeType);
        }
    }

    public Node GetMultipleNode(Node parentNode, INodeGetter nodeGetter)
    {
        foreach (Node child in parentNode.Children)
        {
            return nodeGetter.GetNode(child);
        }
    }

    public Node GetRepeatingNode(Node parentNode, INodeGetter nodeGetter)
    {
        for (int i = 0; i < parentNode.Count; i++)
        {
            // Assume meaningful constructor for Node
            return nodeGetter.GetNode(new Node(i));
        }
    }
}

当测试nodegetter参数时,传递一个mock。

我还将您的方法从私有更改为公开,因为最好只测试您的类的公共接口。

答案 1 :(得分:1)

好吧,你不能“独立”单独测试它们,因为它们显然彼此依赖,但原则上你当然可以为GetNode,GetMultipleNode和GetRepeatingNode编写单独的测试,假设从它们中调用每一个是有意义的。使用它们的代码。当然,GetRepeatingNode调用GetNode,依此类推,但这与调用一些完全外部函数没有区别。

顺便提一下,您可以考虑重构您的设计并使用多态而不是NodeType枚举。只是一个想法:)

答案 2 :(得分:0)

如果确实需要,可以使用接口包装每个方法并为此方法创建模拟(例如使用Moq库)或将方法作为Mark Byers建议的参数相互传递。但似乎这是一个过于复杂的解决方案。

正如我所看到的,代码中的方法是私有的,您确定,为这种低级别的内部实现细节编写单元测试是个好主意吗?我相信这三种方法应该作为一个单元进行测试。这个逻辑分为三种不同的方法,只是为了提高代码的可读性,这不是某种公共API,所以你真的需要独立测试它们吗?