为什么 AutoFixture 无法创建此类?

4

概述

我使用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 的限制或方面我没有注意到或误解了?


1
在我看来,这似乎是一个错误。一个更简单的例子(不需要相互类型递归)已经作为问题记录在Autofixture存储库中:https://github.com/AutoFixture/AutoFixture/issues/1108 - Jeff Dammeyer
1个回答

3
这是因为您添加的OmitOnRecursionBehavior在达到递归限制时会生成一个OmitSpecimen结果。对于属性,这很好用,但对于构造函数调用则不太可行。
我认为解决问题最简单的方法是将OmitOnRecursionBehavior替换为NullRecursionBehavior。
Omit和Null之间的区别在于,NullRecursionBehavior不依赖于返回OmitSpecimen值,而是在递归限制处简单地返回null值。当您有递归类型时,这通常正是您想要的。

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