如何使用模拟匿名类型的设置?
我有以下存储库:
interface IReportingRepository where T: Report { IEnumerable GetReports(object constraints); }
我试图模拟对此存储库的调用:
var reportingRepostory = new Mock(); reportingRepostory.Setup(x => x.GetReports<ServiceReport (Moq.It.IsAny())). Returns(new List(){Report1, Report2});
但不是传入
Moq.It.IsAny()
我想传递匿名类型
new {Activated = true, Enabled = true}
这样我就可以设定使用正确的匿名类型的期望。
您可以使用自定义匹配器以及一些reflection帮助:
var reportingRepostory = new Mock(); reportingRepostory .Setup(x => x.GetReports(HasProperties())) .Returns(new List (){Report1, Report2});
HasProperties
方法的实现方式如下:
private object HasProperties() { return Match.Create( (object o) => { var properties = o.GetType().GetProperties(); return properties.Any(p => p.Name == "Available") && properties.Any(p => p.Name == "Enabled"); }); }
原始解决方案无法获取的一些实现错误:
new {Activated = true, Enabled = false} new {Activated = true, Enabled = true, Extra = "I'm not meant to be here!"} new {Activated = true, Enabled = "true"}
根据IReportingRepository GetReports方法实现的复杂性,可能值得考虑validation匿名类型的属性值和值类型是否符合预期,并且仅存在预期的属性。
var reportingRepostory = new Mock(); reportingRepostory .Setup(x => x.GetReports(IsAnonymousType(new {Activated = true, Enabled = true}))) .Returns(new List (){Report1, Report2});
IsAnonymousType方法的位置是:
private static object IsAnonymousType(object expected) { return Match.Create( (object actual) => { if (expected == null) { if (actual == null) return true; else return false; } else if (actual == null) return false; var expectedPropertyNames = expected.GetType().GetProperties().Select(x => x.Name); var expectedPropertyValues = expected.GetType().GetProperties().Select(x => x.GetValue(expected, null)); var actualPropertyNames = actual.GetType().GetProperties().Select(x => x.Name); var actualPropertyValues = actual.GetType().GetProperties().Select(x => x.GetValue(actual, null)); return expectedPropertyNames.SequenceEqual(actualPropertyNames) && expectedPropertyValues.SequenceEqual(actualPropertyValues); }); }