2016-01-22 4 views
1

Я хотел иметь тестовый пример, где я могу проверить, что список IRule увеличивается при добавлении нового элемента IRule. Метод, который я тестирую, - AddRule. Я хотел сохранить свойство «rules» частным.C# Unit testing. Проверка количества списков

Вот код

public class DefaultRulesManager : IRulesManager 
{ 
    private List<IRule> rules; 

    public DefaultRulesManager() 
    { 
     rules = new List<IRule>(); 
    } 

    public void AddRule(IRule rule) 
    { 
     if (rule == null) 
     { 
      throw new ArgumentNullException("rule must be set"); 
     } 

     rules.Add(rule); 
    } 

    public bool HasPassed<T, SKU>(T obj, SKU s) 
    { 
     IProduct product = (IProduct)obj; 

     return rules.All(x => x.HasPassed(product, s)); 
    } 
} 
+0

Как в стороне, ваш метод 'HasPassed' будет более чисто реализован как' return rules.All (x => x.HasPassed (product, s)); '. У вас немного другое поведение, заметьте - он прекратится, как только он найдет первое ошибочное правило. Если вы хотите, чтобы все правила были оценены, даже если некоторые сбой, вы можете использовать 'return rules.Count (...) == rules.Count;'. –

+0

@JonSkeet спасибо! –

+0

Вывести новое свойство под названием 'RulesCount' или метод' HasRule (IRule) 'и протестировать его? Также почему метод 'HasPassed' принимает' T', когда вы бросаете 'T' на' IProduct'? Не может ли быть 'HasPassed ' или ограничение T быть IProduct? –

ответ

4

Вы можете выставить Count только для чтения свойство, которое возвращает количество rules:

public int RulesCount 
{ 
    get { return rules.Count; } 
} 
4

Существуют различные варианты здесь:

  • Expose rules публично, но безопасно, например через обертку ReadOnlyCollection<T> или как IEnumerable<IRule> через return rules.Select(r => r);, чтобы избежать фактического отображения списка через литье. Это разумно, если у вас нет возражений против звонящих, зная, какие правила находятся в менеджере, если они не могут изменить список, кроме AddRule.
  • Expose rules внутренне (в идеале через свойство - я бы не предложил внутреннее поле, я бы также сделал поле только для чтения) и использовал InternalsVisibleTo, чтобы ваш тестовый доступ к этому. (Вы можете выставить только счет, если хотите, но я не уверен, что это особенно полезно.)
  • Придерживайтесь тестирования публичного API - вы можете проверить, все ли правила, которые вы добавляете в список (в вашем тесте), являются затем консультировался.

Лично я, вероятно, поеду на прежний вариант, но некоторые люди берут «только проверку публичного API», как золотое правило, которое никогда не будет нарушено.

+0

Это хорошая идея? Перечислить список как параметр конструктора, выполнить 'AddRule', а не делать утверждения против списка. – Kote

+0

@ Kote: Нет, я бы не предложил этого. Либо вы захотите сделать это только для внутреннего использования (в любом случае это в принципе эквивалентно), либо он будет общедоступным, и у вас будет список, который вы не могли бы контролировать. Существуют различные способы достижения цели с помощью «внутреннего единственного» подхода, но выявление свойства для существующего поля представляется мне самым простым. –

1

Еще одна идея в верхней части предыдущих ответов - выполнить ваши модульные тесты против класса, который наследует DefaultRulesManager.

Вам нужно будет немного изменить класс DefaultRulesManager, сделав rules членом protected. Унаследованный класс можно назвать DefaultRulesManagerTestable и предоставить общедоступное свойство readonly RulesCount, которое вернет rules.Count.