【问题标题】:Creating public types in AutoFixture 4.8.0 using internal JSON constructors, with many constructor arguments在 AutoFixture 4.8.0 中使用内部 JSON 构造函数创建公共类型,具有许多构造函数参数
【发布时间】:2019-02-13 10:43:19
【问题描述】:

在 AutoFixture 4.8.0 中,除了使用 Fixture.Register 注册函数来创建仅公开 internal 构造函数的类型之外,还有更好的替代方法吗?

在上下文中:

我正在开发一个 .net 标准类库来构建供内部使用的 API。我们不想公开公共构造函数,因此这些模型的所有构造函数都是internal。属性还有public readonly。这些类将通过 Json 反序列化进行实例化,并且在这个特定的库中,有一个模型需要考虑超过 20 个属性。作为奖励,我们希望尽可能使用 [AutoDataAttribute]。

即。除了使用 AutoFixture 提供具有 20 多个参数的内部 jsonconstructor 之外,还有其他方法吗?

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

【问题讨论】:

    标签: c# autofixture


    【解决方案1】:

    默认情况下,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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-08
      • 2011-04-16
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 1970-01-01
      • 2023-01-01
      • 1970-01-01
      相关资源
      最近更新 更多