代码之家  ›  专栏  ›  技术社区  ›  Kevin LaBranche

代码设计/可测试性如何实现?

  •  2
  • Kevin LaBranche  · 技术社区  · 16 年前

    我的团队正在设计一个库,该库包装对Active Directory的调用,以搜索并返回人员列表。

    我们将person类设计为只具有只读(get)属性,因为我们不希望被调用方更改person信息。我们将System.Directory库中的SearchResult对象传递给person的构造函数。

    我的问题是我们不能轻易地测试它。

    到目前为止,我的想法是:

    1. 将需要设置的每个属性的变量传递到person构造函数中。

      不幸的是,这将导致一个很长的构造函数参数列表。。。。我觉得很难闻。

    2. 再说一次,我觉得很难闻,因为我们无法控制被叫人使用这个。

    3. 重构:

    4. 对person对象进行子类化,并使用setters创建一个测试person。。。。

      看起来会有效果,但不确定这是不是正确的方法?

    5. 还没有做过任何嘲弄,所以再次不确定这一点。

    编辑:如果嘲弄是最好的主意,请让我知道。。。然而,我很想知道,如果没有嘲弄,这将如何实现(或者,如果没有嘲弄,这真的是不可能实现的)。。。。

    下面是一段代码:

        public class PeopleSearcher
    {
       .... declarations left out....
    
        public List<Person> FindPerson(string FirstName, string LastName, string Login)
        {
             ...filter setup left out for brevity....
    
             _peopleFound = _directoryToSearch.FindAll();
            //Convert to list of persons....
                int cnt = 0;
                _listOfPeople = new List<Person>();
                while (cnt < _peopleFound.Count)
                {
                    Person p = new Person(_peopleFound[0]);
                    _listOfPeople.Add(p);
                    cnt++;
                }
                return _listOfPeople;
            }
    
        }
    
        public class Person
        {
            private string sn;
            ....further declarations left out for brevity....
    
            public Person(SearchResult PersonFound)
            {
                sn = PersonFound.Properties["sn"].Count == 0 ? string.Empty : PersonFound.Properties["sn"][0].ToString();
                givenName = PersonFound.Properties["givenName"].Count == 0 ? string.Empty : PersonFound.Properties["givenName"][0].ToString();
                sAMAccountName = PersonFound.Properties["sAMAccountName"].Count == 0 ? string.Empty : PersonFound.Properties["sAMAccountName"][0].ToString();
                adsPath = PersonFound.Path == null ? string.Empty : PersonFound.Path;
    
            }
    
            public string LastName
            {
                get
                {
                    return sn;
                }
            }
    
            .... more getters...
         }
    }
    
    3 回复  |  直到 16 年前
        1
  •  1
  •   Cellfish    16 年前

    “Mocking”是一个常用于各种语言的词 test doubles

        2
  •  0
  •   Ben Hughes    16 年前

    当模拟它时,您可能会意识到一些应该重构的领域。这也是一个好计划。

        3
  •  0
  •   CPerkins    16 年前

    幸运的是,有两个很好的解决方案:

    1) 继续向Person类添加setter,但要使其受到保护。这意味着您的模拟和测试代码必须在同一个包中,但会阻止其他用户对您的人员进行变异。(我们不想让变种人到处乱跑——最近电影里已经有足够的变种人了)。

    2) 使用构建器类(正如Joshua Bloch在Java中所描述的那样)。您将在Person内部创建一个公共静态PersonBuilder类,该类将导出一个构建方法和可链接的参数说明符(如setter,但不能单独调用):

    public class Person ....
       public static class PersonBuilder {
          public PersonBuilder (String firstName, String lastName) {...} // my sample has two required values
          public Person build() { ... }
          public PersonBuilder ssn (String value) { ... }
          public PersonBuilder adsPath (String value) { ... }
          ...
       }
       ...
    }
    

          public PersonBuilder ssn (String value) { 
             this.sn = value;
             return this;
          }
    

    然后调用创建一个人,如下所示:

       Person thisPerson = new Person.PersonBuilder ("John", "Smith").ssn("123-45-6789").adsPath("whatever");
    
    

    顺便说一句,您可能还希望将Person的构造函数设置为私有。

    推荐文章