Создание открытых типов в AutoFixture 4.8.0 с использованием внутренних конструкторов JSON со многими аргументами конструктора - PullRequest
0 голосов
/ 13 февраля 2019

Как и в AutoFixture 4.8.0, есть ли лучшая альтернатива использованию Fixture.Register для регистрации функции для создания типа, который предоставляет только конструктор internal?

В контексте:

Я работаю над стандартной библиотекой классов .net для создания API для внутреннего использования.Мы не хотим показывать открытые конструкторы, и поэтому все конструкторы для этих моделей internal.Свойства дополнительно public readonly.Эти классы будут созданы с помощью десериализации Json, и в этой конкретной библиотеке есть модель с> 20 свойствами для рассмотрения.В качестве бонуса мы хотели бы использовать [AutoDataAttribute], где это возможно.

т.е.Есть ли альтернатива снабжению внутреннего jsonconstructor смесью не сложных и сложных типов (также внутренних) с более чем 20 аргументами, используя AutoFixture?

[TestFixture]
public sealed class Tests
{
    private Fixture _fixture;

    [OneTimeSetUp]
    public void OneTimeSetup()
    {
        _fixture = new Fixture();

        _fixture.Register(() => new Vehicle(_fixture.Create<string>(), _fixture.Create<int>()));

        _fixture.Register(
            () => new Driver(_fixture.Create<string>(), _fixture.Create<int>(), _fixture.Create<Vehicle>()));
    }

    [Test]
    public void CanCreateDriverWithVehicle()
    {
        Func<Driver> func = () => _fixture.Create<Driver>();
        func.Should().NotThrow(); // Green
    }
}

[PublicAPI]
public sealed class Driver
{
    public readonly string Name;
    public readonly int Age;
    public Vehicle Vehicle;

    [JsonConstructor]
    internal Driver(string name, int age, Vehicle vehicle)
    {
        Name = name;
        Age = age;
        Vehicle = vehicle;
    }
}

[PublicAPI]
public sealed class Vehicle
{
    public readonly string Manufacturer;
    public readonly int Miles;

    [JsonConstructor]
    internal Vehicle(string manufacturer, int miles)
    {
        Manufacturer = manufacturer;
        Miles = miles;
    }
}

1 Ответ

0 голосов
/ 19 марта 2019

По умолчанию AutoFixture учитывает только общедоступные конструкторы.Он не выбирает внутренние конструкторы, даже если они доступны из сборки выполнения теста (даже не уверен, есть ли техническая возможность проверить это).

Вы можете легко настроить свой прибор для поддержкитот.Получите вдохновение из следующего примера кода:

[Fact]
public void ShouldActivateTypesWithInternalConstructor()
{
    var fixture = new Fixture();

    fixture.ResidueCollectors.Add(
        new Postprocessor(
            new MethodInvoker(
                new ModestInternalConstructorQuery()),
            new AutoPropertiesCommand()
        ));

    var result = fixture.Create<TypeWithInternalConstructor>();

    Assert.NotEqual(0, result.Property);
}

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

        return from ci in type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)
            where ci.IsAssembly // Take internal constructors only
            let parameters = ci.GetParameters()
            where parameters.All(p => p.ParameterType != type)
            orderby parameters.Length ascending
            select new ConstructorMethod(ci) as IMethod;
    }
}

public class TypeWithInternalConstructor
{
    public int Property { get; }

    internal TypeWithInternalConstructor(int property)
    {
        Property = property;
    }
}
...