Tools.Client というプロジェクトで Person クラスを定義しました。これは、Web サービス API のラッパーです。Person は、サービスによって返された XML で構築されます。
public class Person
{
internal Person(XElement personElement)
{
this.FirstName = personElement.Element("first_name").Value;
this.LastName = personElement.Element("last_name").Value;
this.Jobs = new List<Job>();
foreach (var jobElement in personElement.Elements("jobs"))
{
this.Jobs.Add(new Job(jobElement));
}
}
public string FirstName {get; private set;}
public string LastName {get; private set;}
public ICollection<Job> {get; private set;}
}
Tools.Analysis という別のプロジェクトに Analyzer という別のクラスがあります。このプロジェクトには、API クライアントから取得したデータに対して実行する分析ロジックが含まれています。
private readonly ICollection<Person> _people;
public Analyzer(ICollection<Person> people)
{
_people = people;
}
public AnalysisResult Analyze()
{
var result = new AnalysisResult();
foreach (var person in _people)
{
// do some analysis, store data in the result
}
return result;
}
Analyzer クラスの Analyze メソッドの単体テストを書きたいのですが、次の問題を回避する方法がわかりません。
Person には、XElement パラメーターを持つ内部コンストラクター メソッドがあります。単体テストで XElement オブジェクトを手動で作成したくありません。
Personにはプライベートセッターがあります(そうすべきだと思うので、Tools.ClientのユーザーがAPIから返されたデータを変更することは望ましくありません)。この問題は、同様の構造を持つ Job への追加の依存関係によって悪化します。
これに対するいくつかの解決策を考えることができますが、時間の経過とともにどれが最も保守しやすいかわかりません:
- IPerson および IJob インターフェイスを作成し、これらのインターフェイスのモックまたは単純なテスト実装を使用します。
- 簡単にテストできるようにパブリック セッターを公開します (繰り返しますが、これはあまり好きではありません)。InternalsVisibleTo 属性を使用して内部セッターを使用することもできると思います (パブリックほど悪くはありませんが、それでも私が望むものではありません)。
- XML 解析をコンストラクターの外に移動し、コンストラクターにパラメーター firstName、lastName、jobs を取らせます。コンストラクターは引き続き内部にすることができます。アセンブリで InternalsVisibleTo 属性を使用する必要があるだけです。