Как можно избежать добавления геттеров для облегчения модульного тестирования? - PullRequest
6 голосов
/ 19 июля 2011

После прочтения сообщения в блоге , в котором упоминается, как неправильно выставлять общедоступный метод получения информации только для облегчения тестирования, я не смог найти конкретных примеров лучших практик.

Предположим, у нас естьэтот простой пример:

public class ProductNameList
{
    private IList<string> _products;
    public void AddProductName(string productName)
    {
        _products.Add(productName);
    }
}

Скажем, по причинам объектно-ориентированного проектирования у меня нет необходимости публично раскрывать список продуктов.Как тогда я могу проверить, выполняла ли AddProductName () свою работу?(Возможно, продукт был добавлен дважды или не добавлен вовсе.)

Одним из решений является предоставление доступной только для чтения версии _products, где я могу проверить, есть ли у нее только одно название продукта - то, которое я передалAddProductName ().

В блоге, о котором я упоминал ранее, говорится, что речь идет скорее о взаимодействии (т. Е. Добавлено ли название продукта), а не о состоянии.Тем не менее, состояние это именно то, что я проверяю.Я уже знаю, что AddProductName () был вызван - я хочу проверить правильность состояния объекта, как только этот метод выполнил свою работу.

Отказ от ответственности: Хотя этот вопрос похож на Принципы балансировки:Модульное тестирование , (1) язык отличается (C # вместо Java), (2) этот вопрос содержит пример кода, и (3) я не чувствую, что на вопрос был дан адекватный ответ (т. Е. Код помог быпродемонстрировать концепцию).

Ответы [ 4 ]

7 голосов
/ 19 июля 2011

Модульные тесты должны проверять общедоступный API.

Если у вас «нет необходимости публично раскрывать список продуктов», то почему вас волнует, справился ли AddProductName со своей работой? Какая возможная разница, если список будет полностью закрытым и никогда не повлияет на что-либо еще?

Узнайте, что влияет AddProductName на состояние, которое может быть обнаружено с помощью API, и проверьте это.

Очень похожий вопрос здесь: Модель предметной области (предоставление общедоступных свойств)

1 голос
/ 20 июля 2011

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

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

EDIT

Одна вещь, которую вы можете сделать в вашем сценарии, - это иметь конструктора-ублюдка, в который вы добавляете IList, а затем вы проверяете, что добавили продукт:

public class ProductNameList
{
    private IList<string> _products;

    internal ProductNameList(IList<string> products)
    {
        _products = products;
    }
    ...
}

Затем вы бы проверили это так:

[Test]
public void FooTest()
{
    var productList = new List<string>();

    var productNameList = new ProductNameList(productList);

    productNameList.AddProductName("Foo");

    Assert.IsTrue(productList[0] == "Foo");
}

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

0 голосов
/ 20 июля 2011

Чтобы проверить, выполнил ли AddProductName () свою работу, вместо использования открытого метода получения _ProductNames, вызовите GetProductNames () - или эквивалент, определенный в вашем API. Такая функция не обязательно должна быть в одном классе.

Теперь, если ваш API не предоставляет какой-либо способ получения информации о названиях продуктов, то AddProductName () не имеет видимых побочных эффектов (в этом случае это бессмысленная функция).

Если AddProductName () имеет побочные эффекты, но они являются косвенными - скажем, метод в ProductList, который записывает список имен продуктов в файл, то ProductList следует разделить на два класса - один, который управляет списком, и другая вызывает API Add и Get и выполняет побочные эффекты.

0 голосов
/ 19 июля 2011

Сделать _products protected вместо private. В макете вы можете добавить аксессор.

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