简体   繁体   English

为什么 AutoFixture 不能创建这个 class?

[英]Why can't AutoFixture create this class?

Summary概括

I am encountering strange behavior using AutoFixture that seems to be related to class inheritance , recursion , or collections .我在使用 AutoFixture 时遇到了奇怪的行为,这似乎与 class inheritancerecursioncollections 相关 Is there is anything specific I need to do to allow AutoFixture to create these classes?我需要做些什么来允许 AutoFixture 创建这些类吗? Is there some limitation of AutoFixture I am missing?我缺少 AutoFixture 的一些限制吗?

Details细节

Given classes as follows给定类如下

public class SpecificNodeA : BaseNode
{
    public SpecificNodeA(IEnumerable<BaseNode> childNodes) : base(childNodes)
    {
    }
}

public abstract class BaseNode
{
    public List<BaseNode> ChildNodes { get; }

    protected BaseNode(IEnumerable<BaseNode> childNodes)
    {
        ChildNodes = childNodes?.ToList();
    }
}

public class SpecificNodeB : BaseNode
{
    public SpecificNodeB(IEnumerable<BaseNode> childNodes) : base(childNodes)
    {
    }
}

and a test class of和一个测试 class

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void CanGetSpecificNodeA()
    {
        var fixture = GetFixture();
        var node = fixture.Create<SpecificNodeA>();
    }

    [TestMethod]
    public void CanGetSpecificNodeB()
    {
        var fixture = GetFixture();
        var node = fixture.Create<SpecificNodeB>();
    }

    private Fixture GetFixture()
    {
        var fixture = new Fixture();
        fixture.Customizations.Add(
            new TypeRelay(
                typeof(BaseNode),
                typeof(SpecificNodeA)));
        fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
            .ForEach(b => fixture.Behaviors.Remove(b));
        fixture.Behaviors.Add(new OmitOnRecursionBehavior());
        return fixture;
    }
}

I get the error below when trying to create an instance of SpecificNodeB尝试创建SpecificNodeB的实例时出现以下错误

 Test method AutoFixtureTest.UnitTest1.CanGetSpecificNodeB threw exception: 
AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to create an instance from AutoFixtureTest.SpecificNodeA, most likely because it has no public constructor, is an abstract or non-public type.

Request path:
    AutoFixtureTest.SpecificNodeB
      System.Collections.Generic.IEnumerable`1[AutoFixtureTest.BaseNode] childNodes
        System.Collections.Generic.IEnumerable`1[AutoFixtureTest.BaseNode]
          AutoFixtureTest.BaseNode
            AutoFixtureTest.SpecificNodeA

If However I change the classes to not have the collection (as below) they work fine但是,如果我将类更改为没有集合(如下所示),它们可以正常工作

public class SpecificNodeA : BaseNode
{
    public SpecificNodeA(int nodeId) : base(nodeId)
    {
    }
}

public abstract class BaseNode
{
    public int NodeId { get; }

    protected BaseNode(int nodeId)
    {
        NodeId = nodeId;
    }
}

public class SpecificNodeB : BaseNode
{
    public SpecificNodeB(int nodeId) : base(nodeId)
    {
    }
}

It seems odd to me that AutoFixture can not create these classes since they are fairly simple and the error message indicating it AutoFixture 无法创建这些类对我来说似乎很奇怪,因为它们相当简单并且错误消息表明它

was unable to create an instance from AutoFixtureTest.SpecificNodeA无法从 AutoFixtureTest.SpecificNodeA 创建实例

doesn't make sense since it clearly can as seen in the first unit test.没有意义,因为它清楚地可以在第一个单元测试中看到。

Is there is anything specific I need to do to allow AutoFixture to create these classes?我需要做些什么来允许 AutoFixture 创建这些类吗? Is there some limitation or aspect of AutoFixture I am missing or missunderstanding?我缺少或误解了 AutoFixture 的某些限制或方面吗?

This happens because the OmitOnRecursionBehavior you added will generate an OmitSpecimen result when it reaches the recursion limit.发生这种情况是因为您添加的 OmitOnRecursionBehavior 将在达到递归限制时生成 OmitSpecimen 结果。 This works fine for properties, but does not work for constructor calls.这适用于属性,但不适用于构造函数调用。

I think the simplest solution to your problem is to replace the OmitOnRecursionBehavior with NullRecursionBehavior.我认为解决您的问题的最简单方法是将 OmitOnRecursionBehavior 替换为 NullRecursionBehavior。

The difference between Omit and Null is that NullRecursionBehavior will not rely on returning OmitSpecimen values, but will simply return null values at the recursion limit. Omit 和 Null 之间的区别在于 NullRecursionBehavior 将不依赖于返回 OmitSpecimen 值,而只是在递归限制处返回 null 值。 This is often exactly what you want when you have recursive types.当您有递归类型时,这通常正是您想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM