C# 如何让Autofixture创建包含接口类型属性的类型实例?

C# 如何让Autofixture创建包含接口类型属性的类型实例?,c#,autofixture,test-data,C#,Autofixture,Test Data,我有这样一门课: public class ViewModel { public IPagination<Data> List { get; set; } // interface! public SearchFilter SearchFilter { get; set; } public string Test { get; set; } } public class SearchFilter { public string Name { get;

我有这样一门课:

public class ViewModel
{
    public IPagination<Data> List { get; set; } // interface!
    public SearchFilter SearchFilter { get; set; }
    public string Test { get; set; }
}

public class SearchFilter
{
    public string Name { get; set; }
}

一种简单的可能性是注册工厂方法:

fixture.Register<YourInterface>(() =>  new InterfaceImpl());

理论上,应该可以填充自动模拟实例的属性

假设
ViewModel
类型的
IPagination
属性定义为:

public interface IPagination<T>
{
    SearchFilter Property1 { get; set; }
    string Property2 { get; set; }
}
然后,以下调用将创建
ViewModel
(仅在运行时已知)的实例,提供
IPagination的自动模拟实例,并为属性赋值。

var value = context.Resolve(typeof(ViewModel));
// List -> {IPagination`1Proxy593314cf4c134c5193c0019045c05a80}
// List.Property1.Name -> "Namef71b8571-a1a0-421d-9211-5048c96d891b" 
// List.Property2 -> "f58cae65-b704-43ec-b2ce-582a5e6177e6"
MyCustomization 在应用此定制之前,请记住,这只适用于此特定场景(因此描述中的特殊场景)。我强烈建议使用其中一个用于自动模拟的扩展,或其他任何地方

内部类MyCustomization:ICCustomization
{
公共空间自定义(iTexture装置)
{
fixture.Customizations.Add(新的MySpecimenBuilder());
}
私有类MySpecimenBuilder:ISpecimenBuilder
{
公共对象创建(对象请求,ISPecementContext上下文)
{
var type=请求类型;
if(type==null | |!type.IsInterface)
{
返回新的NoSpecimen(请求);
}
对象样本=此
.GetType()
.GetMethod(
“创建”,
BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(新[]{type})
.Invoke(这个新对象[]{context});
返回样本;
}
私有静态对象创建(ISpecimenContext上下文)
特雷奎斯特:课堂在哪里
{
var mock=new mock();
mock.SetupAllProperties();
foreach(PropertyInfo-propInfo类型为(TRequest.GetProperties())
{
对象值=context.Resolve(propInfo.PropertyType);
propInfo.SetValue(mock.Object,value);
}
返回mock.Object;
}
}
}

视图模型和上一个问题的答案与问题的最后一句有什么关系?请关注您的问题。您是对的,我脑子里有这么多问题:)是否也可以让Autofixture围绕接口创建一个动态代理并用测试数据填充它?是否可以用数据填充创建的代理列表?调用
mock.SetupAllProperties()不是更容易一点吗
?使实现更加简单。下面介绍如何配置以设置所有模拟实例以及自动填充其属性。
public interface IPagination<T>
{
    SearchFilter Property1 { get; set; }
    string Property2 { get; set; }
}
var fixture = new Fixture()
    .Customize(new MyCustomization());
var context = new SpecimenContext(fixture.Compose());
var value = context.Resolve(typeof(ViewModel));
// List -> {IPagination`1Proxy593314cf4c134c5193c0019045c05a80}
// List.Property1.Name -> "Namef71b8571-a1a0-421d-9211-5048c96d891b" 
// List.Property2 -> "f58cae65-b704-43ec-b2ce-582a5e6177e6"
internal class MyCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new MySpecimenBuilder());
    }

    private class MySpecimenBuilder : ISpecimenBuilder
    {
        public object Create(object request, ISpecimenContext context)
        {
            var type = request as Type;
            if (type == null || !type.IsInterface)
            {
                return new NoSpecimen(request);
            }

            object specimen = this
                .GetType()
                .GetMethod(
                    "Create",
                    BindingFlags.NonPublic | BindingFlags.Static)
                .MakeGenericMethod(new[] { type })
                .Invoke(this, new object[] { context });

            return specimen;
        }

        private static object Create<TRequest>(ISpecimenContext context)
            where TRequest : class
        {
            var mock = new Mock<TRequest>();
            mock.SetupAllProperties();

            foreach (PropertyInfo propInfo in typeof(TRequest).GetProperties())
            {
                object value = context.Resolve(propInfo.PropertyType);
                propInfo.SetValue(mock.Object, value);
            }
            return mock.Object;
        }
    }
}