2009-08-22 11 views
2

私のチームは、Active Directoryへの呼び出しをラッピングして人のリストを検索して返すライブラリを設計しています。コードデザイン/テスト容易性How To?

私たちには、見つかった人の情報をまとめた人のクラスがあります。その後、リストを使用してそれらをまとめます。検索を呼び出すと、内部System.Directoryライブラリが使用され、SearchResultCollectionオブジェクトが返されます。その後、それを繰り返してリスト<>を構築し、それを返します。

私たちは、被呼者が個人情報を変更しないようにするために、読者限定(取得)プロパティのみを持つように個人クラスを設計しました。人のコンストラクタのSystem.DirectoryライブラリからSearchResultオブジェクトを渡します。

私の問題は、これを簡単にテストできないことです。

私の考えでは、これまでされています

  1. パス変数に設定される必要がある各プロパティの人物のコンストラクタに。

    残念ながら、これは非常に長いコンストラクタパラメータリストになります....私には悪い匂いがする。

  2. 人物クラスがプロパティにセッターを持つことを許可します。

    これも、私たちが着メロを使用するのを制御することができないので、私にとっては悪いことです。

  3. リファクタリング:私はインターフェイスとパラメータの技法を適用するエキスを見てきました

    。それは適応パラメータが最も有望であるようですか? Adaptパラメータは、ディレクトリライブラリのSearchResultオブジェクトの依存関係を解消するのに役立ちます。だから将来的に私たちは良い形になっている他の種類の検索をしたいと思っています。少なくとも私はそうだと思いますか?それは動作しますが、それは行くための正しい方法かどうかわからないのと同じよう

  4. サブクラスpersonオブジェクトとセッターを持つ被験者を作成する....

    らしいですか?

  5. は、任意のこの1についてわからないので、もう一度、まだモックそれは

    は行っていないモック。

EDIT:モックが最高のアイデアである場合しかし、私は、これはまた、モックせずに実行される方法を知って興味がある(または多分それは本当にあざけるせずにできはしないさ)...私に教えてください....

私はこの1つの指針をいただきたいと思います。

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... 
    } 
} 

答えて

1

「モッキング」は、通常、すべての種類のtest doublesに使用されている単語です。そして、ほとんどの人は、 "嘲笑"していない、彼らは偽造やスタブしている。とにかく、Personオブジェクトが他のメソッドに渡されることを前提に、あなたのコードベースを与えるための最も簡単な方法のように、私の4番目のオプション(サブクラスとセッターを追加)が私に鳴ります。人のオブジェクトがコンストラクタによってプロパティが正しく設定されているかどうかをテストしているとは思わないので、そうですか?

+0

正しい。私は検索から返された人のリストをテストしています。私は正しく働いている人間のコンストラクタについて心配していません。 – klabranche

+0

adaptパラメータはどうですか?この種のリファクタリング技術を行うには、これがすばらしい場所であるかどうかを知りたいのは本当に興味がありますか? – klabranche

+1

はい、ディレクトリライブラリオブジェクトへの依存を解除することは、確かに良い方法です。その場合、Personクラスをサブクラス化する必要はありません。偽の「適合」オブジェクトを与えてください。コードがTDDを使用して作成されていれば、おそらくあなたは終わっただろうと思います。 – Cellfish

0

がそれをモック:

は、ここでのコードの抜粋です。これは嘲笑が発明されたような状況です。私はRubyで嘲笑しただけなので、.netのための最先端技術はわかりませんが、うまくいくはずです。

リバースしなければならない領域があるかもしれません。これはまた良い計画です。

+0

私はそれのためだけに嘲笑を避けるべきだった場合。次善の方法は何でしょうか? – klabranche

+0

私はそれを何とか模倣してしまいます(モックフレームワークを明示的に使わなくても)。これを行う1つの方法は、SearchResultをサブクラス化して、プロパティを自分自身のデータ構造に設定するためにイニシャライザをオーバーライドすることです。これはまだまだ嘲りで、ちょっとだけハックされています。 –

+0

ベンに感謝します。これは私のアイデアの1つであり、それが私にとってこれを行うなら、それは嘲笑的なフレームワークが適しているということです。 – klabranche

0

あなたのモックでは(フレームワークなどで)、値を持つPersonオブジェクトを作成しなければならなくなり、元の問題に戻ります。

1)先に行くと、Personクラスにセッターを追加し、それらを保護します:

は幸いなことに、2つの優れたソリューションがあります。つまり、モックとテストコードは同じパッケージになければならないが、他のユーザーがあなたのPersonに変更を加えるのを妨げることになる。 (そして、私たちは突然変異体が走っていることを望んでいません - 最近、映画に十分なものがありました)。

2)Builderクラスを使用します(Joshua BlochがEffective Javaで説明しているように)。あなたは、パブリック静的PersonBuilderの(セッターのような、しかし個別呼び出し可能ではない)のビルド方法とチェーン可能パラメータ指定子をエクスポートするだろう人の内部クラスを作成したい:

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

この方法は、完全に(実際の値を設定できるメソッドを隠しますあなたは "setter"を持っていませんが)、長いコンストラクタの引数リストを扱わなくても済みます(オプション値を扱いやすくなります)。

ちなみに、Personのコンストラクタをprivateにしたいと思うかもしれません。