c# - 使用内部 JSON 构造函数在 AutoFixture 4.8.0 中创建公共(public)类型,并带有许多构造函数参数

标签 c# autofixture

与 AutoFixture 4.8.0 一样,是否有更好的替代方法来使用 Fixture.Register 注册函数来创建仅公开内部构造函数的类型?

上下文:

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

即。是否有其他方法可以使用 AutoFixture 提供具有 20 多个参数的非类型和复杂类型(也是内部类型)混合的内部 json 构造函数?

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

最佳答案

默认情况下,AutoFixture 仅考虑公共(public)构造函数。它不会获取内部构造函数,即使它们可以从测试执行程序集访问(甚至不确定是否有合理的技术可能性来检查)。

您可以轻松定制您的装置来支持这一点。从以下代码示例中获取灵感:

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

关于c# - 使用内部 JSON 构造函数在 AutoFixture 4.8.0 中创建公共(public)类型,并带有许多构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54668249/

相关文章:

c# - Autofixture 生成不重复的集合(按 ID)

c# - 使用 LINQ2SQL DataContext 表作为其 ItemsSource 时使用 DataGrid 的正确方法(最佳实践)

c# - 我是否应该使用 AutoFixture 来测试我的 Onion 的核心元素(它没有依赖项)?

C# 使用位图 LockBits 处理 bmp 图像。尝试更改所有字节,但保存后其中一些字节的值仍然为 0。为什么?

c# - 如何以一定的延迟启动 MS TPL 的任务类实例?

c# - AutoFixture:PropertyData 和异构参数

c# - 我可以在 XUnit 构造函数中自定义 Fixture 以与 Theory 和 AutoData 一起使用吗?

c# - 类中的 AutoFixture 设置界面属性

c# - Visual Studio在azure中的wwwroot内部署文件夹在哪里

C# 架构验证返回 false 成功