C# 单元测试。验证列表计数

C# Unit testing. Verify list count

我想要一个测试用例,我可以在其中验证 IRule 计数列表随着新 IRule 项的添加而增加。我正在测试的方法是 AddRule。我想将 'rules' 属性 保密。

这是代码

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));
    }
}

您可以公开 Count 只读 属性,returns rules 的计数:

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

这里有多种选择:

  • 公开rules public但安全,例如通过 ReadOnlyCollection<T> 包装器或通过 return rules.Select(r => r); 作为 IEnumerable<IRule> 以避免实际列表通过转换暴露。如果您不反对调用者知道管理器中的规则,这是合理的,只要他们不能修改列表,除非通过 AddRule.
  • 在内部公开 rules(最好通过 属性 - 我不建议使用内部字段;我也会将该字段设置为只读),并使用 InternalsVisibleTo 允许你的测试访问权限。 (如果你愿意,你可以只公开计数,但我不确定它是否特别有用。)
  • 坚持测试 public API - 你可以检查你添加到列表中的所有规则(在你的测试中)然后是否被参考。

就我个人而言,我可能会选择前一种选择 - 但有些人认为 "only test the public API" 是一条永远不能被打破的黄金法则。

还有一个想法,在之前的答案之上是针对继承 DefaultRulesManager.

的 class 执行单元测试

您必须通过让 rules 成为 protected 成员来稍微更改 DefaultRulesManager class。继承 class 可以命名为 DefaultRulesManagerTestable 并提供 public readonly 属性 RulesCount 这将 return rules.Count.