【问题标题】:What are the good practice to test/inject private field in C#在 C# 中测试/注入私有字段的好习惯是什么
【发布时间】:2012-07-18 21:59:24
【问题描述】:

如果这是重复的,我深表歉意。我被赋予了为该方法添加一些覆盖范围的任务,并被告知要模拟私有 List<string> 属性。我的问题是:有没有办法测试私有字段?

我找到的解决方案是添加新的构造函数来注入这个私有列表。我不确定这是否是正确的方法,因此我们将不胜感激。

public class Class1
{
    public Class1(List<string> list)//This is just for Unit Testing 
    {
        list1 = list;
    }


    private readonly InjectRepository _repository;
    //
    public Class1(InjectRepository repository)//This is the actual constructor
    {
        _repository = repository;
    }

    private List<string> list1 = new List<string>();

    public void Do_Complex_Logic()
    {
       //list1 will be set with items in it
       //Now list1 is passed to some other instance
    }
}

【问题讨论】:

标签: c# unit-testing tdd code-coverage


【解决方案1】:

类的私有逻辑应该在其行为的公共表达中可见。换句话说,理论上来说,根本不需要测试私有字段。

没有办法直接测试私有字段;毕竟他们是私人的。如果您确实认为需要测试私有字段,那么我建议将其改为内部字段,并通过 [InternalsVisibleTo] 属性将其公开给您的单元测试程序集。

话虽如此,有些框架允许这样的事情,例如TypeMock

【讨论】:

    【解决方案2】:

    不要测试私有字段或方法。测试合约的行为 - 公共或内部方法。

    也就是说,你可以试试:

    选项 A
    private 成员设为 internal 并为被测程序集设置 InternalsVisibleTo 属性。

    选项 B
    编写一个包装类,将您的私有字段/方法包装到公共字段/方法中。这种方法的一个好处是您不需要将私有方法设为内部。不利的一面是,对于每个私有方法,您都将拥有一个包装器公共方法。所以方法的数量可能会翻倍。

    【讨论】:

      【解决方案3】:

      补充一下 womp 和 oleksii 已经说过的话 -

      您想要/需要测试私有方法这一事实表明您的设计可能不正确。这是 TDD 的积极副作用之一(也是我个人最喜欢的)。

      一个例子:

      我在这里不完全了解您的域,但一个简单的更改可能是,而不是 Do_Complex_Logic 不带参数,您可以让它带并返回 List&lt;string&gt;

      public List&lt;string&gt; Do_Complex_Logic( List&lt;string&gt; input )

      我知道 - 这很简单,但请尝试稍微解构您的类,并首先考虑测试并重新构建它。

      【讨论】:

      • +1 - 我同意,如果您需要将这些东西作为私有测试,这通常表明出现问题。
      【解决方案4】:

      我不反对其他答案;但在这种情况下,我认为最合适的做法是 - 给定您的代码;是改变签名的

      'Do_Complex_Logic'

      真正的问题是您正在处理 List1 的“状态”。如果您将 List1 传递给 Do_Complex_Logic - 您的问题基本解决了。您的评论说“Do_Complex_Logic”将(大概)在 List1 上做一些工作,然后将其传递给其他东西,对吧?

      使 Do_Complex_Logic 接受一个列表并返回一个列表。现在很容易测试。您可以“注入依赖项”,而不是依赖于您的班级中正确设置的 List1 的状态。

      【讨论】:

        【解决方案5】:

        首先如何准备私有字段?如果是通过与存储库的交互,那么您可能会模拟该对象。

        做到这一点的一种方法是通过接口与您的存储库进行交互(我们将其称为IInjectRepository 而不是具体实体,然后使用类似Moq 的东西(或那里的众多模拟框架之一)在设置测试时通过模拟存储库填充数据。在您调用 Do_Complex_Logic 之后,我假设您有一种询问实体的方法,以便您知道它已经完成了您的预期。这样您可以避免/mitigate 添加仅用于测试的方法和类。

        【讨论】:

          【解决方案6】:

          您可以在回答https://stackoverflow.com/a/3376157/1523402 的相关问题时使用reflection
          我不知道私有访问器是否也适用于私有字段。但它们(至少)有助于私有方法(参见http://msdn.microsoft.com/en-us/library/ms184807%28v=vs.80%29.aspx)。

          【讨论】:

            猜你喜欢
            • 2017-11-23
            • 2012-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-25
            • 2012-09-12
            • 2013-05-01
            • 1970-01-01
            相关资源
            最近更新 更多