如何使用流畅的断言比较对象图中的嵌套列表
How to compare nested lists in object graphs using fluent assertions
如果我有一个包含列表的预期对象图,如下所示:
var expectedExperiment = new Experiment
{
Number= "12345",
AllocatedInstrument = "Instrument 1",
Experimenters = new List<Experimenter>
{
new Experimenter
{
Name = "Sue"
Role = "Scientist",
Id = 1,
Initials = "S"
},
new Experimenter()
{
Name = "Mark",
Role = "Technician",
Id = 2,
Initials = "M"
},
}
};
当我只想在子对象列表中包含某些属性时,如何将它与我的实际对象进行比较。
例如,我想写这样的东西来比较所有父对象属性和一些子对象属性:
actualExperiment.ShouldBeEquivalentTo(expectedExperiment, options => options
.Including(o => o.Number)
.Including(o => o.AllocatedInstrument)
.Including(o => o.Experimenters.Select(e => e.Role))
.Including(o => o.Experimenters.Select(e => e.Name)));
但我得到一个例外:
System.ArgumentException : Expression <o.Experimenters.Select(e => e.Role)> cannot be used to select a member.
在这种情况下,我不介意子项的顺序,但我想断言我关心的属性符合预期。
您可以通过检查运行-时间类型和当前对象的选定成员路径来做到这一点:
.Including(subjectInfo => subjectInfo.RuntimeType == typeof(Experimenter) &&
subjectInfo.SelectedMemberPath.EndsWith("Role"))
这可以提取到一个方法中以供进一步重用:
private Expression<Func<ISubjectInfo, bool>> BuildMemberExpression<TSource, TProperty>(Expression<Func<TSource,TProperty>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression == null)
{
throw new NotSupportedException();
}
return subjectInfo => subjectInfo.RuntimeType == typeof(TSource) &&
subjectInfo.SelectedMemberPath.EndsWith(memberExpression.Member.Name);
}
现在这样使用:
.Including(BuildMemberExpression((Experimenter e) => e.Name))
.Including(BuildMemberExpression((Experimenter e) => e.Role))
如果我有一个包含列表的预期对象图,如下所示:
var expectedExperiment = new Experiment
{
Number= "12345",
AllocatedInstrument = "Instrument 1",
Experimenters = new List<Experimenter>
{
new Experimenter
{
Name = "Sue"
Role = "Scientist",
Id = 1,
Initials = "S"
},
new Experimenter()
{
Name = "Mark",
Role = "Technician",
Id = 2,
Initials = "M"
},
}
};
当我只想在子对象列表中包含某些属性时,如何将它与我的实际对象进行比较。
例如,我想写这样的东西来比较所有父对象属性和一些子对象属性:
actualExperiment.ShouldBeEquivalentTo(expectedExperiment, options => options
.Including(o => o.Number)
.Including(o => o.AllocatedInstrument)
.Including(o => o.Experimenters.Select(e => e.Role))
.Including(o => o.Experimenters.Select(e => e.Name)));
但我得到一个例外:
System.ArgumentException : Expression <o.Experimenters.Select(e => e.Role)> cannot be used to select a member.
在这种情况下,我不介意子项的顺序,但我想断言我关心的属性符合预期。
您可以通过检查运行-时间类型和当前对象的选定成员路径来做到这一点:
.Including(subjectInfo => subjectInfo.RuntimeType == typeof(Experimenter) &&
subjectInfo.SelectedMemberPath.EndsWith("Role"))
这可以提取到一个方法中以供进一步重用:
private Expression<Func<ISubjectInfo, bool>> BuildMemberExpression<TSource, TProperty>(Expression<Func<TSource,TProperty>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression == null)
{
throw new NotSupportedException();
}
return subjectInfo => subjectInfo.RuntimeType == typeof(TSource) &&
subjectInfo.SelectedMemberPath.EndsWith(memberExpression.Member.Name);
}
现在这样使用:
.Including(BuildMemberExpression((Experimenter e) => e.Name))
.Including(BuildMemberExpression((Experimenter e) => e.Role))