首页 > 解决方案 > 为什么 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 的某些限制或方面吗?

标签: c#.netunit-testingautofixture

解决方案


发生这种情况是因为您添加的 OmitOnRecursionBehavior 将在达到递归限制时生成 OmitSpecimen 结果。这适用于属性,但不适用于构造函数调用。

我认为解决您的问题的最简单方法是将 OmitOnRecursionBehavior 替换为 NullRecursionBehavior。

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


推荐阅读