9

我有这样一堂课:

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

围绕 IPagination 接口创建一个动态代理,并用测试数据填充代理。现在是否可以让 AutoFixture 创建 ViewModel 类型的实例?请注意,我只知道运行时的类型 ( typeof(ViewModel))。

现在我知道我可以做到这一点:

var context = new SpecimenContext(fixture.Compose());
var value = context.Resolve(new SeededRequest(typeof(ViewModel), null))
4

2 回答 2

5

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

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

要让 AutoFixture 自动为您想要使用自动模拟自定义项之一的接口创建代理:

  • AutoMoq定制
  • AutoRhinoMock定制
  • AutoFakeItEasy定制

在您的具体情况下,这将创建一个表示空列表的接口实例。
当您想在该列表中包含测试数据时,您不想使用自动模拟自定义,而是使用理解语义的自定义,IPagination本博客文章中所述。
如果这太复杂,您仍然可以使用以下Register方法:

fixture.Register(() => (IPagination<Data>)new Pagination(
                                            fixture.CreateMany<Data>()));
于 2012-10-18T07:49:24.583 回答
4

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

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

public interface IPagination<T>
{
    SearchFilter Property1 { get; set; }
    string Property2 { get; set; }
}

我们可以创建一个临时的自动模拟自定义,例如MyCustomization.

var fixture = new Fixture()
    .Customize(new MyCustomization());
var context = new SpecimenContext(fixture.Compose());

然后,以下调用将创建一个实例ViewModel (仅在运行时知道),提供一个自动模拟实例,IPagination<Data>为属性赋值。

var value = context.Resolve(typeof(ViewModel));
// List -> {IPagination`1Proxy593314cf4c134c5193c0019045c05a80}
// List.Property1.Name -> "Namef71b8571-a1a0-421d-9211-5048c96d891b" 
// List.Property2 -> "f58cae65-b704-43ec-b2ce-582a5e6177e6"

我的定制

在应用此自定义之前,请记住这仅适用于此特定场景(因此描述中的临时)。我强烈建议在其他任何地方使用 Auto Mocking、AutoMoqAutoRhinoMocksAutoFakeItEasyAutoNSubstitute的扩展之一。

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;
        }
    }
}
于 2012-10-18T15:31:19.337 回答