【问题标题】:Can Autofixture create an anonymous type?Autofixture 可以创建匿名类型吗?
【发布时间】:2016-04-11 15:04:52
【问题描述】:

假设我想在单元测试中调用返回一个看起来像这样的匿名类型 -

var anonymousType = { id = 45, Name="MyName", Description="Whatever" }

Autofixture 可以生成anonymousType 吗?如果有,语法是什么?

【问题讨论】:

  • 考虑避免匿名类型,因为它们对系统的其他部分不太透明。您总是创建一个 DTO 对象,或者只使用 Dictionary<... ...>。每当您希望使用匿名类型时,请三思而后行,然后考虑使用 DTO ;) .

标签: c# unit-testing autofixture


【解决方案1】:

不,AutoFixture 不支持匿名类型,因为它们位于使用它们的库的内部。

【讨论】:

    【解决方案2】:

    作为@MarkSeemann pointed out,AutoFixture不能支持匿名类型。

    关于 AutoFixture 和 dynamic 的注意事项

    这可能不适用于您的具体情况,但我认为值得一提的是,如果您需要在测试中创建 动态类型对象 的实例,并且您并不关心它们的特定状态– 您可以配置 AutoFixture 以创建 DynamicObject 的实例,以响应您在它们上调用的任何属性或方法。

    这是一个例子:

    public class DynamicCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customizations.Insert(
                0,
                new FilteringSpecimenBuilder(
                    new FixedBuilder(new AnythingObject()),
                    new ExactTypeSpecification(typeof(object))));
        }
    
        private class AnythingObject : DynamicObject
        {
            public override bool TryGetMember(
                GetMemberBinder binder,
                out object result)
            {
                result = new AnythingObject();
                return true;
            }
    
            public override bool TryInvokeMember(
                InvokeMemberBinder binder,
                object[] args,
                out object result)
            {
                result = new AnythingObject();
                return true;
            }
        }
    }
    

    在这种情况下,AnythingObject 只是为它接收到的调用的任何属性或方法返回一个自身的新实例。例如,这将允许您说:

    var fixture = new Fixture();
    fixture.Customize(new DynamicCustomization());
    
    var foo = fixture.Create<dynamic>();
    
    Assert.NotNull(foo.Bar);
    Assert.NotNull(foo.Baz());
    

    另一种选择——尽管更脆弱——可能是使用 AutoFixture 为特定属性创建值。在这种情况下,您必须将 Fixture 对象传递给 AnythingObject,如下例所示:

    public class DynamicCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customizations.Insert(
                0,
                new FilteringSpecimenBuilder(
                    new FixedBuilder(new AnythingObject(fixture)),
                    new ExactTypeSpecification(typeof(object))));
        }
    
        private class AnythingObject : DynamicObject
        {
            private readonly SpecimenContext context;
    
            public AnythingObject(ISpecimenBuilder builder)
            {
                context = new SpecimenContext(builder);
            }
    
            public override bool TryGetMember(
                GetMemberBinder binder,
                out object result)
            {
                if (binder.Name == "Bar")
                {
                    result = context.Resolve(typeof(string));
                }
                else
                {
                    result = new AnythingObject(context.Builder);
                }
    
                return true;
            }
    
            public override bool TryInvokeMember(
                InvokeMemberBinder binder,
                object[] args,
                out object result)
            {
                result = new AnythingObject(context.Builder);
                return true;
            }
        }
    }
    

    在这里,我们正在寻找一个名为"Bar" 的属性并为其提供string,而其他所有内容都将获得AnythingObject 的实例。所以我们可以说:

    var fixture = new Fixture();
    fixture.Customize(new DynamicCustomization());
    
    var foo = fixture.Create<dynamic>();
    
    Assert.IsType<string>(foo.Bar);
    Assert.NotNull(foo.Baz);
    

    【讨论】:

    • 虽然马克的答案是答案,但这很有趣,我一定会玩的。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    相关资源
    最近更新 更多