如何使用模拟匿名类型的设置?

我有以下存储库:

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); }); }