Autofixture 从具有不可访问的内部构造函数的第 3 方库创建 class

Autofixture create class from 3rd party library that has an inaccessible internal constructor

我想使用 Autofixture 创建一个 class 的实例,我正在使用第 3 方库。

我面临的问题是这个 class 的构造函数有一个内部访问修饰符,并且来自第 3 方解决方案我不能真正使用 InternalsVisibleTo 属性,所以我想知道是否有任何可以使用的 Autofixture 行为,或者是否有任何替代技术可以应用于此类场景。

public class RecordedEvent
  {
    /// <summary>The Event Stream that this event belongs to</summary>
    public readonly string EventStreamId;
    /// <summary>The Unique Identifier representing this event</summary>
    public readonly Guid EventId;
    /// <summary>The number of this event in the stream</summary>
    .....

    internal RecordedEvent(....)
    {
      .....
    }
  }

OOTB,AutoFixture 试图找到能够创建 class 实例的 public 构造函数或静态工厂方法。由于您不拥有 RecordedEvent 并且无法添加 public 构造函数,因此您必须 AutoFixture 如何实例化它。有一种称为 Customizations 的机制可以用于此目的。

首先你创建一个自定义,它能够找到一个类型的所有内部构造函数:

public class InternalConstructorCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customize<RecordedEvent>(c =>
            c.FromFactory(
                new MethodInvoker(
                    new InternalConstructorQuery())));
    }

    private class InternalConstructorQuery : IMethodQuery
    {
        public IEnumerable<IMethod> SelectMethods(Type type)
        {
            if (type == null) { throw new ArgumentNullException(nameof(type)); }

            return from ci in type.GetTypeInfo()
                    .GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)
                   select new ConstructorMethod(ci) as IMethod;
        }
    }
}

然后你将它应用到你的 Fixture:

var fixture = new Fixture()
    .Customize(new InternalConstructorCustomization());

然后您可以创建 RecordedEvent class:

的实例
var recordedEvent = fixture.Create<RecordedEvent>(); // does not throw