我在名为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有私有的setter(我认为它应该,我不希望Tools.Client的用户改变从API返回的数据)。 Job的附加依赖性加剧了这个问题,Job具有类似的结构。
我可以想到一些解决方案,但不知道哪个是最容易维护的:
答案 0 :(得分:4)
我认为你应该将xml解析从Person
移动到一个单独的类似工厂的类中,使Person
不可变的值类对象类。这样您就不需要模拟它们,您应该能够创建Person
和Job
的真实实例来测试Analyzer
。
答案 1 :(得分:0)
我同意你不想让你的主持人公开。你现在有一个不可变的课程,你不应该轻易放弃。
值对象的接口没问题,但它们经常被过度设计。如果有更好的解决方案,请避免使用。
使用选项3. Xml解析实际上是另一个类的责任; Person
应该只是一个数据对象。
如果你不能这样做,至少要创建一个没有它的构造函数。这不是很好,因为你的构造函数可能会分歧(它们不能轻易地相互调用),但它比你的位置更好。
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));
}
}
internal Person(string firstName, string lastName, ICollection<Job> jobs)
{
//set properties
}
public string FirstName {get; private set;}
public string LastName {get; private set;}
public ICollection<Job> {get; private set;}
}