为什么AutoFixture无法创建此类?

问题描述

摘要

我在使用AutoFixture时遇到了奇怪的行为,该行为似乎与类继承递归集合有关。要允许AutoFixture创建这些类,我需要做些什么特定的事情?我缺少AutoFixture的某些限制吗?

详细信息

给出如下类

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)
    {
    }
}

一个测试类

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

尝试创建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

如果但是我将类更改为没有集合(如下所示),则它们工作正常

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)
    {
    }
}

对于我来说,AutoFixture无法创建这些类似乎很奇怪,因为它们非常简单,并且错误消息指出了这些情况

无法从AutoFixtureTest.SpecificNodeA创建实例

没有意义,因为在第一次单元测试中显然可以理解。

要允许AutoFixture创建这些类,我需要做些特定的事情吗?我缺少或误会了AutoFixture的某些限制或方面吗?

解决方法

之所以发生这种情况,是因为您添加的OmitOnRecursionBehavior在达到递归限制时将生成OmitSpecimen结果。这对于属性很好,但对构造函数调用无效。

我认为最简单的解决方案是用NullRecursionBehavior替换OmitOnRecursionBehavior。

Omit和Null之间的区别在于NullRecursionBehavior将不依赖于返回OmitSpecimen值,而是仅在递归限制处返回null值。当您具有递归类型时,这通常正是您想要的。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...