【问题标题】:UnitTesting Properties in .Net?.Net 中的单元测试属性?
【发布时间】:2009-02-27 07:44:58
【问题描述】:

我正在开发一个我想以开源方式发布的库。我已经开始为代码编写测试,我想知道我应该如何测试 .Net 对象中的属性。假设我有以下内容:

public class Person{ #region variables private string _name = String.Empty; private string _surname = String.Empty; #region properties public string Name{ get{ return _name; } } public string Surname{ get{ return _surname; } set{ _surname = value; } } }

我有两个与代码相关的问题:

  1. 如何对仅具有 getter 的属性(如示例中的名称)进行单元测试
  2. 如何使用 setter 和 getter 对属性进行单元测试(如示例中的姓氏)

我想测试这么简单的属性,因为我已经在其他代码中发现错误是 Itellinsense 执行了错误的自动完成并且属性没有返回正确的变量。

更新:

我不是在谈论示例中的简单属性,它们背后确实有一些逻辑并且很难调试。编写一个使用 setter 来测试 getter 的测试,反之亦然是不好的,因为如果失败,我将不知道应该归咎于哪个方法。我正在使用属性,因为它们被添加为公共变量,后来必须添加更多逻辑。

【问题讨论】:

  • 提供一个更接近您实际使用的示例。让回答更容易。
  • > “它们背后确实有一些逻辑,而且很难调试。”听起来可能需要进行一些重构,然后您可以对逻辑的特定元素进行单元测试。

标签: c# .net unit-testing testing


【解决方案1】:

别把时间浪费在写傻话上 测试 getter 和 setter。

另一个测试可能会设置 命名然后获取该属性,以便您 将具有代码覆盖率 吸气剂。

您应该测试任何面向公众的东西,包括属性。如果你不测试一个属性,你就会冒有人可能会在其中添加一些逻辑从而破坏功能的风险。

此外,您不应依赖它在其他测试中的测试。这会使您的测试变得脆弱,并且更难确定问题出在哪里,因为测试将测试不止一件事。

【讨论】:

  • 您当然“可以”为所有公共成员编写测试,但如果您对单元测试的成本/收益方面感兴趣,那么不,不要对所有公开的内容编写单元测试。确实,您不想在像不包含逻辑的属性(简单的 getter/setter)这样简单的东西上编写测试。你从那个测试中得到什么好处?如果您的论点是有人可能会稍后出现并添加逻辑,那么这就是应该添加测试的时候。
  • 对 setter 进行单元测试的一个好时机,我已经完成了,当 setter 更改数据时,例如检查字符串的长度,屏蔽除最后 4 个字符之外的所有字符。诸如此类的事情,在 getter 中有预期的逻辑。我认为单元测试很好。
【解决方案2】:

如何对一个属性进行单元测试 只是有一个吸气剂(就像名称中的 例子)

如果你有一个二传手,这与测试真的没有什么不同。您只需要找到另一种确定输出的方法。可能在 ctor 中,或对象上其他设置器/操作的结果。

[Test]
public void NamePropTest()
{
    Person p = new Person();

    //Some code here that will set up the Person object
    //  so that you know what the name will be

    Assert.AreEqual("some known value...", p.Name);
}

如果我们有 Name 和 SurName 的 setter,但只有 FullName 的 getter,则测试可能如下所示:

[Test]
public void NamePropTest()
{
    Person p = new Person();

    p.Name = "Sean";
    p.Surname = "Penn";

    Assert.AreEqual("Sean Penn", p.FullName);
}

【讨论】:

    【解决方案3】:

    您应该测试属性。还有自动属性!

    单元测试是关于确保对程序进行更改,不要破坏程序。

    您最终可能会在某个时间更改属性实现,并且您希望确保程序仍按预期运行。您可以通过测试来做到这一点。

    即使您使用自动属性(作为字段/成员变量的替代品),将它们设置为属性的原因是您以后想更改它们的实现。然后你会希望测试在那里。

    编辑:(回应 shahkalpesh 的评论...)

    如果您要更改 实施,测试也可能 需要改变。所以,我不知道 为什么有人应该测试简单 获取/设置?

    从这个类开始:

    public class TimeOfDay
    {
        public int Hour{get; private set;}
        public int Minute{get; private set;}
    
        public TimeOfDay(int hour, int minute)
        {
            Hour = hour;
            Minute = minute;
        }
    }
    

    更改实现时,测试仍然有效!

    public class TimeOfDay
    {
        public int _minutesSinceMidnight = 0;
    
        public int Hour
        {
            get { return _minutesSinceMidnight / 60; }
            set { _minutesSinceMidnight = value * 60 + Minutes; }
        }
    
        public int Minute
        {
            get { return _minutesSinceMidnight % 60; }
            set { _minutesSinceMidnight = Hour * 60 + value; }
        }
    
        public TimeOfDay(int hour, int minute)
        {
            Hour = hour;
            Minute = minute;
        }
    }
    

    加入一些日期和时间算术函数或其他东西,我希望测试表明一切仍然有效......

    【讨论】:

    • 如果您要更改实现,测试可能也需要更改。所以,我不知道为什么有人应该测试简单的 get/set?
    • @shahkalpesh:我还是会写一个测试。更改需求通常会导致更改测试(不仅针对属性)。我不能不写测试,因为它可能需要在将来的某个时候进行更改。 (我还在回答中添加了一个示例说明原因。)
    • 我可以提出另一种观点吗?如果要编写复杂的逻辑,特别是如果它可能会引发异常,从语义上讲,最好将它们编写为方法而不是属性。然后,关于该方法是否具有覆盖率也是一个更容易讨论的问题。
    【解决方案4】:

    我认为你应该测试它们,如果你像以前那样编写它们。毕竟你可能会打错一些东西。

    有点像

    var person = New Person();
    person.Surname = "test";
    Assert.AreEqual("test", person.Surname);
    

    毕竟,TDD 和单元测试一般都是为了尽可能避免大多数错误。

    如果你不小心写了这个。

    public class Person{
        #region variables
        private string _name = String.Empty;
        private string _surname = String.Empty;
        #region properties
        public string Name{
            get{
                 return _name;
            }
        }
        public string Surname{
            get{
                return _name;
            }
            set{
                _name = value;
            }
        }
    }
    

    那么你就会有一个错误。

    测试自动属性可能价值不大。但这是另一个问题。

    【讨论】:

    • 那么,如果测试失败,如何打包,getter 还是 setter?示例中的属性很简单,但现实世界中的属性并不简单,而且它们很难调试。
    • 然后问你想问的问题,不要试图过于简单化。人们只会回答问题,而不是您认为的问题。
    • @chrissie 我不认为编写 200 行代码是一个好主意,如果我在哪里使用简单的属性,我什至不会编写它们,而是让编译器为我完成工作。跨度>
    • 所以你肯定应该对它们进行测试。但是,如果您在 setter 中有 200 行代码,那么您就会遇到 SRP 问题。如果我们必须猜测问题,我们无法为您提供建议。
    • 我虽然单一职责原则 (SRP) 专注于类而不是方法或属性。在这种情况下,对象正在处理他的数据,唯一的问题是它以一种懒惰的方式执行它并且必须检查数据库。
    【解决方案5】:

    这些属性应该存在,因为您有需要它们的用途。至于这些应该有单元测试,你应该已经覆盖了它们。 如果没有需要它们的场景,它们可能根本就不应该存在。

    【讨论】:

    • 我的问题与如何编写测试有关。我一直在考虑它,我需要访问私有值以确保属性按预期工作,否则我不知道该怎么做。
    【解决方案6】:

    据我了解,您不应该测试属性(即那些简单的 get/set)。

    我不确定您使用的是什么版本的 c#。但是,您可以使用自动属性来避免您面临的简单设置/获取问题。

    看到这个link

    【讨论】:

      【解决方案7】:

      不要把时间浪费在为 getter 和 setter 编写愚蠢的测试上。

      另一个测试可能会设置 Name 然后获取该属性,这样您就可以覆盖 getter 的代码。

      【讨论】:

      • @mandel 明确指出他的属性有逻辑,因此测试必须支持该逻辑。​​
      【解决方案8】:

      我的问题与如何 写测试。我一直在想 关于它,我需要访问 私有值,以确保 属性按预期工作,否则 我不知道怎么做。 https://stackoverflow.com/users/59332/mandel

      好吧……既然你坚持要知道怎么做……

      [Test]
      TestMethod()
      {
      
          Person p = new Person();
          p.Name = "a name";
          p.Surname = "a surname";
      
          Assert.That(p.Name, Is.EqualTo("a name"));
          Assert.That(p.Surname, Is.EqualTo("a surname"));
      }
      

      但是,这只有在你有 setter 时才有效....

      如果你只有吸气剂,我能想到的只有两种方法可以做到这一点。

      1. 提前知道返回值并反对它。
      2. 使用反射设置值,然后针对该已知值进行断言。

      更好的建议是放弃并测试一些真正为您的软件增加价值的有价值的东西。测试 getter 和 setter 绝对是浪费时间,除非它们背后有复杂的事情发生......这种情况很少发生。

      【讨论】:

      • 是的,但是在这种情况下,您的测试使 getter 和 setter 相关联,这意味着在某些时候您假设 getter 或 setter 确实有效。它还假设您在 Name 中有一个 getter,但事实并非如此......属性很简单,因为它们是示例......
      【解决方案9】:

      我认为您的意思是您的 getter-only 属性使用私有字段或其他私有数据。如果您需要设置它们,唯一的方法是通过反射获取它们(查看 System.Reflection 中的所有(某些)信息类)。但是,如果这是一种好的做法,则需要进行激烈的讨论。

      【讨论】:

      • 如果他创建了只有反射才能获得的变量,我会感到惊讶。这些变量将有一个值,并且可能还有一种设置该值的方式(如果它不是默认值),即使它不像设置属性那么简单。
      • 是的,但我认为他想测试这个单个元素,以便那些私有字段的输入不会受到干扰。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多