在运行时填充对象

时间:2017-06-27 15:52:21

标签: autofixture

我的问题有点奇怪,我认为这不是Autofixture可以解决的问题,而是在这里;

我们有一个测试循环遍历程序集中的每个ICloneable并尝试克隆它。目前我想要摆脱和替换一种可怕的Populate方法。它检查每个属性的类型并根据它分配一个默认值(一个漂亮的,大的,if if语句)。

我遇到的问题是我不想维护Autofixture.Register方法的特定列表,因为这比方法本身更加维护。

有什么想法吗?

感谢。

private void CheckAssemblyClones(Assembly entitiesAssembly)
{
    foreach (Type entityType in entitiesAssembly.GetTypes()
        .Where(t => t.GetInterfaces().Contains(typeof(ICloneable))
                    && !t.IsAbstract
                    && t.GetConstructor(Type.EmptyTypes) != null))
    {
        ICloneable original = Activator.CreateInstance(entityType) as ICloneable;

        //Horrible method is used here to populate the object
        //This is where I tried to add fixture.Create(original) but it
        //doesn't like this original is an interface. If I use entityType
        //directly it complains as there are interfaces within the class
        //implementations that are later fulfilled using an IoC
        PopulateProperties(original, true);

        //Tried this, which fails because it is an ICloneable
        //var fixture = new Fixture();
        //original = fixture.Create(original);

        MethodInfo cloneMethod = entityType.GetMethod("Clone", new Type[]
        {
            typeof(Boolean)
        });
        object clone = cloneMethod.Invoke(original, new object[]
        {
            true
        });
    }
}

private static PropertyInfo[] PopulateProperties(object obj, bool nest)
{
    //var fixture = new Fixture();
    var properties = obj.GetType().GetProperties();

    foreach (PropertyInfo property in properties)
    {
        //Tried this but it failed due to PropertyInfo being an abstract class.
        //var autoProp = fixture.Create(property);
        //For every type set a default value for the property
    }

    return properties;
}

1 个答案:

答案 0 :(得分:1)

听起来你正在尝试编写一个涵盖多种类型行为的基于约定的测试。这就是AutoFixture.Idioms的用途。

勾勒出一个可能的实现,你应该考虑定义一个派生自IdiomaticAssertion的类:

public class CloneableAssertion : IdiomaticAssertion
{
    private readonly ISpecimenBuilder builder;

    public CloneableAssertion(ISpecimenBuilder builder)
    {
        if (builder == null)
            throw new ArgumentNullException("builder");

        this.builder = builder;
    }

    public override void Verify(Type type)
    {
        // Check if type is ICloneable before trying to create it.
        // Return if it's not ICloneable.

        // If this.builder is a standard Fixture object, the returned
        // object will be populated with data, if possible.
        var sut = (ICloneable)Create(type);

        // Insert test against sut here...
    }

    private object Create(Type type)
    {
        return new SpecimenContext(this.builder).Resolve(type);
    }
}

有关更全面的示例,请参阅AutoFixture.Idioms的源代码。最好的起点可能是WritablePropertyAssertion,它相当小而且简单。

也许您只是为了内部使用而实施ICloneable,在这种情况下它很好,但是您应该知道它的使用是discouraged in public APIs:< / p>

  

我们建议不要在公共API中实现ICloneable