C #: Unittesting с закрытыми статическими членами? - PullRequest
10 голосов
/ 04 октября 2011

У меня есть класс с такой конструкцией:

private static Dictionary<Contract, IPriceHistoryManager> _historyManagers = new Dictionary<Contract, IPriceHistoryManager>();

и, скажем, 2 метода, таких как:

 public void AddSth()
 {
    _historManagers.Add(new Contract(), new PriceHistoryManager());
 }

 public int CountDic()
 {
    return _historyManagers.Count(); 
 }

Проблема: При выполнении юнит-тестов тамневозможно «сбросить» словарь, и когда я создаю несколько юнит-тестов с отдельными экземплярами класса, то «CountDic» дает непредсказуемые результаты, и я не могу проверить списки.

Вопрос: Считается ли это обычно "плохим" подходом, и если да, то как это сделать лучше / более единообразно?А если нет: как лучше всего протестировать это?

Thx.

Ответы [ 2 ]

21 голосов
/ 04 октября 2011

Не бойтесь выставлять публичные операции в целях тестирования. Перефразированный из «Искусства модульного тестирования» Роя Ошерова: Когда Toyota строит автомобиль, есть доступные точки тестирования. Когда Intel строит чип, есть доступные точки тестирования. Существуют интерфейсы для автомобиля или чипа, которые существуют только для тестирования. Почему мы не делаем то же самое для программного обеспечения? Будет ли метод ResetHistory() полностью уничтожить ваш API?

Если этот ответ yes, то создайте метод, но сделайте метод internal. Затем вы можете использовать сборку InternalsVisibleTo, чтобы открыть для себя внутреннюю библиотеку юнит-тестов. У вас есть доступный метод, созданный для тестирования на 100%, но в вашем общедоступном API нет никаких изменений.

3 голосов
/ 04 октября 2011

В вашем примере CountDic не является непредсказуемым: он должен вернуть на единицу больше, чем до вызова AddSth().

Итак:

[Test]
public void Test()
{
    var item = new ClassUnderTest();
    int initialCount = item.CountDic();

    item.AddSth();

    int finalCount = item.CountDic();

    Assert.That(finalCount == initialCount + 1);
}

В целом, тестирование классов, которые поддерживают состояние, может быть сложным. Иногда необходимо выделить часть класса, которая поддерживает состояние (в вашем случае, словарь) и переместить его в другой класс. Затем вы можете смоделировать этот класс «storage» и передать его через конструктор.

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