我正在使用 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
一种可能的方法:
var parameterHandler = fixture.Create<ITemplateParameterHandler>();
var segmentHandler = fixture.Build<TemplateSegmentHandler>()
.FromFactory(() => new TemplateSegmentHandler(parameterHandler));
fixture.Inject(segmentHandler);
我最终实现了 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))
)
)
);