2008-09-19 3 views
2

У меня есть следующий сценарий:Какова стратегия модульного тестирования для переадресации вызовов метода?

 
public class CarManager 
{ 
    .. 

    public long AddCar(Car car) 
    { 
     try 
     { 
     string username = _authorizationManager.GetUsername(); 
     ... 
     long id = _carAccessor.AddCar(username, car.Id, car.Name, ....); 
     if(id == 0) 
     { 
      throw new Exception("Car was not added"); 
     } 
     return id; 
     } catch (Exception ex) { 
     throw new AddCarException(ex); 
     } 
    } 

    public List AddCars(List cars) 
    { 
    List ids = new List(); 
    foreach(Car car in cars) 
    { 
     ids.Add(AddCar(car)); 
    } 
    return ids; 
    } 
} 

Я насмешливый из _reportAccessor, _authorizationManager и т.д.

Теперь я хочу UnitTest класс CarManager. Должен ли я иметь несколько тестов для AddCar(), такие как

 
AddCarTest() 
AddCarTestAuthorizationManagerException() 
AddCarTestCarAccessorNoId() 
AddCarTestCarAccessorException() 

Для AddCars() я должен повторить все предыдущие тесты, как AddCars() вызывает AddCar() - похоже, повторяя себя? Должен ли я, возможно, не называть AddCar() из AddCars()? < p />

Пожалуйста, помогите.

+0

код не полностью отображается, пытаясь исправить – Xerx 2008-09-19 11:19:07

ответ

1

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

Предположим, у вас есть класс (CarRegistry), который использует какой-то объект доступа к данным (например, CarPlatesDAO), который загружает/сохраняет номера автомобильных номеров из реляционной базы данных.

Когда вы тестируете CarRegistry, вам не стоит заботиться о том, правильно ли работает CarPlateDAO; Поскольку наш DAO имеет собственный модульный тест.

Вы просто создаете макет, который ведет себя как DAO и возвращает правильные или неправильные значения в соответствии с ожидаемым поведением. Вы подключаете этот макет DAO к вашему CarRegistry и проверяете только целевой класс, не заботясь, если все агрегированные классы «зеленые».

Mocking позволяет разделять тестируемые классы и лучше ориентироваться на конкретные функции.

2

Есть две проблемы:

  • Юнит-тесты должны делать больше, чем методы испытаний по одному за раз. Они должны быть разработаны для того, чтобы доказать, что ваш класс может выполнять работу, для которой он был разработан, когда он интегрирован с остальной частью системы. Таким образом, вы должны издеваться над зависимостями, а затем писать тест для каждого способа, которым будет использоваться ваш класс. Для каждого (нетривиального) класса вы пишете сценарии, которые включают методы вызова кода клиента в определенном шаблоне.
  • Нет ничего плохого в том, что AddCars вызывает AddCar. Вы должны повторять тесты для обработки ошибок, но только тогда, когда они служат цели. Одним из неофициальных правил модульного тестирования является «испытание до скуки» или (как мне нравится думать об этом) «тест, пока не исчезнет страх». В противном случае вы будете писать тесты навсегда. Поэтому, если вы уверены, что тест не добавит никакой ценности, они не напишут. Возможно, вы ошибаетесь, и в этом случае вы можете вернуться позже и добавить его. Вам не нужно производить идеальный тест в первый раз, просто прочную основу, на которой вы можете построить, поскольку вы лучше понимаете, что ваш класс необходимо сделать.
+0

+1 для прагматического подхода к тестированию. Кроме того, не вызывать AddCar из AddCars было бы ужасным нарушением принципа DRY. – 2009-01-29 14:13:55

1

При удалении класса AddCar создайте тесты, которые будут выполнять каждую кодировку. Если _authorizationManager.GetUsername() может генерировать исключение, создайте тест, в котором будет выполняться ваш макет для этого объекта. BTW: не бросайте и не улавливайте экземпляры Exception, а выводите осмысленный класс Exception.

Для метода AddCars вам обязательно нужно позвонить в AddCar. Но вы можете подумать о том, чтобы сделать AddCar виртуальным и переопределить его, чтобы проверить, что он вызван со всеми автомобилями в списке.

Иногда вам придется изменить класс для проверки.

1

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

В ситуации, как AddCars() вызова AddCar() Я бы издеваться метод AddCar() и подсчитать, сколько раз она вызывается AddCars(). Издевательская библиотека, которую я использую, позволяет мне создать макет CarManager и высмеивать только метод AddCar(), но не AddCars(). Тогда ваш блок тестирование может установить, сколько раз он ожидает AddCar() называться которые вы должны знать, от размера списка автомобилей, переданных в.

+0

Будете ли вы издеваемым методом AddCar возвращать из него все различные исключения, чтобы тестировать их в AddCars, или считаете, что это избыточно, поскольку оно проверено в тестах AddCar? – Xerx 2008-09-19 12:55:50

1

Должен ли я иметь несколько тестов для AddCar(), таких как

AddCarTest() AddCarTestAuthorizationManagerException() AddCarTestCarAccessorNoId() AddCarTestCarAccessorException()

Абсолютно! Это говорит вам ценную информацию

Для AddCars() я должен повторить все предыдущие тесты, как AddCars() вызывает AddCar() - это кажется как повторять себя? Должен ли я, возможно, не называть AddCar() из AddCars()?

Вызов AddCar из AddCars - отличная идея, это позволяет избежать нарушения принципа DRY. Аналогичным образом, вы должны повторять тесты. Подумайте об этом так: Вы уже писали тесты для AddCar, поэтому при тестировании AddCard вы можете предположить, что AddCar делает то, что он говорит на олове.

Скажем так: представьте, что AddCar был в другом классе. Вы не знали бы менеджера авторизации. Test AddCars без знание того, что должен делать AddCar.

Для AddCars вам необходимо протестировать все обычные граничные условия (работает пустой список и т. Д.). Вероятно, вам не нужно проверять ситуацию, когда AddCar выдает исключение, поскольку вы не пытаетесь его поймать в AddCars.

Смежные вопросы