Autofixture能否创建匿名类型?

7

假设我想在单元测试中调用并返回一个匿名类型,该类型如下所示 -

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

Autofixture能生成匿名类型吗?如果可以的话,它的语法是什么?

考虑避免使用匿名类型,因为它们对系统的其他部分不太透明。您可以始终创建DTO对象或仅使用Dictionary<...,...>。每当您希望使用匿名类型时,请三思而后行,并考虑使用DTO ;)。 - Maris
2个回答

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

2

正如 @MarkSeemann 指出 的那样,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);

虽然Mark的回答是最佳答案,但这个也很有趣,我一定会试试。非常感谢。 - Rich Bryant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接