C# 使用内部构造函数和私有setter对域对象进行单元测试
我在一个名为Tools.Client的项目中定义了一个Person类,它是web服务API的包装器。Person是使用服务返回的XML构造的C# 使用内部构造函数和私有setter对域对象进行单元测试,c#,unit-testing,mocking,C#,Unit Testing,Mocking,我在一个名为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
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;}
}
公共类人物
{
内部人员(XElement人员Element)
{
this.FirstName=personElement.Element(“first_name”).值;
this.LastName=personElement.Element(“last_name”).Value;
this.Jobs=新列表();
foreach(personElement.Elements(“作业”)中的var jobElement)
{
this.Jobs.Add(newjob(jobElement));
}
}
公共字符串名{get;private set;}
公共字符串LastName{get;private set;}
公共ICollection{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;
}
private readonly ICollection\u个人;
公共分析器(ICollection人员)
{
_人=人;
}
公共分析结果分析()
{
var result=新的AnalysisResult();
foreach(var人员在_人员中)
{
//做一些分析,在结果中存储数据
}
返回结果;
}
我想为Analyzer类的Analyze方法编写一个单元测试,但我不确定如何绕过以下问题:
我认为应该将xml解析从
Person
移动到一个单独的类似工厂的类中,使Person
成为类似于类的不可变值对象。这样,您就不需要模拟它们了,您应该能够创建Person
和Job
的真实实例来测试Analyzer
我认为您应该将xml解析从Person
移动到一个单独的类似工厂的类中,使Person
成为类似于类的不可变值对象。这样你就不需要模仿他们了,你应该能够为测试分析器创建Person
和Job
的真实实例。我同意你不想公开你的设置程序。您现在有了一个不可变的类,您不应该轻易放弃它
值对象上的接口是可以的,但它们通常设计过度。如果有更好的解决方案,请避免这样做
选择3。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));
}
}
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;}
}
公共类人物
{
内部人员(XElement人员Element)
{
this.FirstName=personElement.Element(“first_name”).值;
this.LastName=personElement.Element(“last_name”).Value;
this.Jobs=新列表();
foreach(personElement.Elements(“作业”)中的var jobElement)
{
this.Jobs.Add(newjob(jobElement));
}
}
内部人员(字符串名、字符串名、ICollection作业)
{
//设置属性
}
公共字符串名{get;private set;}
公共字符串LastName{get;private set;}
公共ICollection{get;private set;}
}
我同意你不想公开你的设定者。您现在有了一个不可变的类,您不应该轻易放弃它
值对象上的接口是可以的,但它们通常设计过度。如果有更好的解决方案,请避免这样做
选择3。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));
}
}
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;}
}
公共类人物
{
内部人员(XElement人员Element)
{
this.FirstName=personElement.Element(“first_name”).值;
this.LastName=personElement.Element(“last_name”).Value;
this.Jobs=新列表();
foreach(personElement.Elements(“作业”)中的var jobElement)
{
this.Jobs.Add(newjob(jobElement));
}
}
内部人员(字符串名、字符串名、ICollection作业)
{
//设置属性
}
公共字符串名{get;private set;}
公共字符串LastName{get;private set;}
公共ICollection{get;private set;}
}
同意。Xml解析不应该是Person类的责任。违反SRP,IMHO。我想我是在写问题时得出这个结论的,但有一些验证是很好的,谢谢:)同意。Xml解析不应该是Person类的责任。违反SRP,IMHO。我想我是在写问题时得出这个结论的,但是有一些验证是很好的,谢谢:)