Передать локальную переменную в метод в том же классе для тестируемости?

1

У меня есть метод, который обращается к переменным, локальным для самого класса. Мне интересно, есть ли недостаток дизайна, потому что теперь мои модульные тесты зависят от установленных переменных. Это странно/неправильно передавать эти переменные методу, хотя этот метод имеет прямой доступ к этим переменным? (Если метод принимает эти переменные в качестве параметров, то unit тест может также передавать свои собственные переменные методу.)

Например, вот переменные, локальные для класса:

private static List<string> _whitelistNames = GetWhitelistNamesFromConfig();
private static List<string> _blacklistNames = GetBlacklistNamesFromConfig();

И метод выглядит примерно так:

    private static bool ThisProcessorHandlesThisFoo(Foo foo)
    {
        if (_whitelistNames.Count > 0)
        {
            // We're doing this instead of Contains() so we can ignore case sensitivity.
            bool found = ListContainsString(_whitelistNames, foo.Name, StringComparison.OrdinalIgnoreCase);

            // Some logging here

            return found;
        }

        if (_blacklistNames.Count > 0)
        {
            bool found = ListContainsString(_blacklistNames, foo.Name, StringComparison.OrdinalIgnoreCase);

            // Some logging

            return !found;
        }

        throw new InvalidOperationException("some message");
    }

Чтобы сделать то, что я предлагаю, мне нужно будет изменить подпись метода на это:

private static bool ThisProcessorHandlesThisFoo(Foo foo, List<string> whitelistNames, List<string> blacklistNames)

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

Теги:
unit-testing

2 ответа

1
Лучший ответ

Тебе не стоит беспокоиться об этом.

В ваших модульных тестах должен быть проверен интерфейс для вашего класса (общедоступные методы и свойства) и не должен зависеть от какой-либо детали реализации (например, свойства частного класса). Это позволяет изменять реализацию без нарушения другого кода (и, надеюсь, без нарушения существующих тестов).

Те частные статические поля должны быть инициализированы при создании экземпляра класса (в соответствии с вашим кодом, у них есть инициализаторы). Они инициализируются, когда они создаются для вашего модульного теста? Они должны быть... Общепринятой идеей, что, когда конструктор для объекта закончен, класс должен находиться в пригодном для использования состоянии, и вы указываете, что это не всегда так.

Это пример того, где может быть полезно что-то вроде Injection Dependency. Затем вы передаете эти вещи конструктору своего класса (или другим способом) и разрешаете части программы, которые его создают (либо вашу обычную программу, либо ваш unit тест), чтобы "ввести" их в класс.

  • 0
    Похоже, тестирование частных методов - это хорошая битва, в которой есть люди по обе стороны проблемы: stackoverflow.com/a/34586/279516
1
  1. Вам не следует проверять private методы, проверять public в том, как тесты охватывают все ветки кода класса (в том числе и private).
  2. Я бы рекомендовал вам сменить подпись метода (на ThisProcessorHandlesThisFoo(Foo foo, List<string> whitelistNames, List<string> blacklistNames)), а не на использование полей. По моему опыту, такой подход облегчает чтение и обслуживание классов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню