简体   繁体   English

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

[英]How to use setup of a mocked anonymous type?

I have the following repository: 我有以下存储库:

interface IReportingRepository where T: Report
{
     IEnumerable<T> GetReports<T>(object constraints);
}

and I am trying to mock out a call to this repository as: 我试图模拟对此存储库的调用:

var reportingRepostory = new Mock<IReportingRepository>();
                       reportingRepostory.Setup(x => 
                       x.GetReports<ServiceReport (Moq.It.IsAny<object>())).
                       Returns(new List<ServiceReport>(){Report1, Report2});

However instead of passing in 但不是传入

Moq.It.IsAny<object>()

I want to pass the anonymous type 我想传递匿名类型

new {Activated = true, Enabled = true}

so that I can setup my expectation that the correct anonymous type is used. 这样我就可以设定使用正确的匿名类型的期望。

You can use custom matchers with a bit of reflection help: 您可以使用自定义匹配器以及一些反射帮助:

var reportingRepostory = new Mock<IReportingRepository>();
reportingRepostory
    .Setup(x => x.GetReports<ServiceReport>(HasProperties()))
    .Returns(new List<ServiceReport>(){Report1, Report2});

Where HasProperties method is implemented as follows: 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");
        });
}    

A few implementation bugs that won't be picked up by the original solution: 原始解决方案无法获取的一些实现错误:

new {Activated = true, Enabled = false}
new {Activated = true, Enabled = true, Extra = "I'm not meant to be here!"}
new {Activated = true, Enabled = "true"}

Depending on the complexity of your IReportingRepository GetReports method implementations it may be worth considering verifying the anonymous type's property values and value types are as expected and that only exactly the properties expected are present. 根据IReportingRepository GetReports方法实现的复杂性,可能值得考虑验证匿名类型的属性值和值类型是否符合预期,并且仅存在预期的属性。

var reportingRepostory = new Mock<IReportingRepository>();
reportingRepostory
    .Setup(x => x.GetReports<ServiceReport>(IsAnonymousType(new {Activated = true, Enabled = true})))
    .Returns(new List<ServiceReport>(){Report1, Report2});

Where the IsAnonymousType method is: 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);
        });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM