Как вы тестируете взаимно-рекурсивные методы? - PullRequest
7 голосов
/ 20 января 2011

У меня есть три функции, которые выглядят примерно так:

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 ]

5 голосов
/ 20 января 2011

Обычно вам не нужно тестировать каждый метод по отдельности - вы можете просто проверить, что метод верхнего уровня делает правильные вещи.

Однако если по какой-то причине вы хотите протестировать каждый метод отдельно, вы можете использовать внедрение зависимостей так же, как вы тестировали бы любой метод, имеющий зависимости. Единственная разница здесь заключается в том, что зависимость - это сам объект. Вот пример кода для демонстрации идеи:

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 передайте макет.

Я также изменил ваши методы с приватного на общедоступный, потому что лучше тестировать только публичный интерфейс вашего класса.

1 голос
/ 20 января 2011

Ну, вы не можете тестировать их «независимо», поскольку они, очевидно, зависят друг от друга, но в принципе вы, безусловно, можете написать отдельные тесты для GetNode, GetMultipleNode и GetRepeatingNode, предполагая, что имеет смысл вызывать каждый из них изкод, который использует их.Конечно, GetRepeatingNode вызывает GetNode и так далее, но это ничем не отличается от вызова некоторой полностью внешней функции.

Кстати, вы можете рассмотреть возможность рефакторинга вашего дизайна и использовать полиморфизм вместо перечисления NodeType.Просто идея:)

0 голосов
/ 20 января 2011

Если это действительно необходимо, вы можете обернуть каждый метод интерфейсом и создать макеты для этих методов (например, с использованием библиотеки Moq) или передать методы друг другу в качестве параметров, как предлагает Марк Байерс.Но, похоже, это слишком сложное решение.

Как я вижу, что методы из вашего кода являются частными, вы уверены, что это хорошая идея - написать модульные тесты для такого низкого уровня внутренних деталей реализации?Я считаю, что эти три метода должны быть проверены как единое целое.Эта логика разделена на три разных метода только для улучшения читабельности кода, и это не какой-то публичный API, так что вам действительно нужно тестировать их независимо?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...