使用 AutoFixture 选择特定的构造函数

问题描述 投票:0回答:2

我正在使用 AutoFixture,并且我想使用特定的构造函数。

我有以下代码,我喜欢使用 ITemplateParameterHandler 选择构造函数。

public sealed class TemplateSegmentHandler : ITemplateSegmentHandler
{
    public TemplateSegmentHandler(ITemplateIterator iterator)
        : this(new TemplateParameterHandler(iterator))
    {
        Contract.Requires(iterator != null);
    }

    public TemplateSegmentHandler(ITemplateParameterHandler parameterHandler)
    {
        Contract.Requires(parameterHandler != null);

        _parameterHandler = parameterHandler;

        _parameterHandler.Ending += EndingParameter;
    }

    // ...
}

编辑:

我想注入以下假实现。 (我正在使用 NSubstitute 来创建假对象。)

public sealed class CustomTemplateParameter : ICustomization
{
    private readonly ITemplateParameterHandler _context;

    public CustomTemplateParameter()
    {
        _context = Substitute.For<ITemplateParameterHandler>();
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customize<ITemplateParameterHandler>(c => c.FromFactory(() => _context));
    }

    public CustomTemplateParameter SetCatchAll(bool isCatchAll)
    {
        _context.IsCatchAll.Returns(isCatchAll);

        return this;
    }
}

这是我尝试使用它的方式。

[Fact]
public void Should_return_true_when_the_segment_has_a_catch_all_parameter()
{
    TemplateSegmentHandler segmentHandler = new Fixture().Customize(new TemplateSegmentHandlerFixture())
                                                         .Customize(new CustomTemplateParameterHandler()
                                                                        .SetCatchAll(true))
                                                         .Create<TemplateSegmentHandler>();

    segmentHandler.Parameter.Start();
    segmentHandler.Parameter.End();

    segmentHandler.HasCatchAll.Should().BeTrue();
}

但它仍然选择了错误的构造函数,我收到以下错误。

Ploeh.AutoFixture.ObjectCreationExceptionAutoFixture was unable to create an instance from Somia.Web.Routing.Template.ITemplateIterator, most likely because it has no public constructor, is an abstract or non-public type.

Request path:
      Somia.Web.Routing.Template.TemplateSegmentHandler --> 
       Somia.Web.Routing.Template.ITemplateIterator iterator --> 
        Somia.Web.Routing.Template.ITemplateIterator
c# autofixture
2个回答
4
投票

一种可能的方法:

var parameterHandler = fixture.Create<ITemplateParameterHandler>();

var segmentHandler = fixture.Build<TemplateSegmentHandler>()
                            .FromFactory(() => new TemplateSegmentHandler(parameterHandler));

fixture.Inject(segmentHandler);

4
投票

我最终实现了 IMethodQuery 并选择了我想要的 ctor。

public sealed class SelectedFirstConstructorQuery : IMethodQuery
{
    private readonly Type _type;

    public SelectedFirstConstructorQuery(Type type)
    {
        _type = type;
    }

    public IEnumerable<IMethod> SelectMethods(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }

        return from ci in type.GetConstructors()
               let parameter = ci.GetParameters().First()
               where parameter.ParameterType == _type
               select new ConstructorMethod(ci) as IMethod;
    }
}

用途:

fixture.Customize<TemplateSegmentHandler>(
    c => c.FromFactory(
        new MethodInvoker(
            new SelectedFirstConstructorQuery(typeof(ITemplateParameterHandler))
        )
    )
);
© www.soinside.com 2019 - 2024. All rights reserved.