Skip to content

Instantly share code, notes, and snippets.

@aivascu
Last active November 18, 2021 09:34
Show Gist options
  • Save aivascu/f7567bec83fd0dd79c12d0a7871abc92 to your computer and use it in GitHub Desktop.
Save aivascu/f7567bec83fd0dd79c12d0a7871abc92 to your computer and use it in GitHub Desktop.
Demonstrates the use of parameter customization attributes
using AutoFixture.Dsl;
using AutoFixture.Kernel;
using AutoFixture.Xunit2;
using System;
using System.Reflection;
using Xunit;
namespace AutoFixture.Issue1302
{
public class ParameterDecoratorTests
{
[Theory, AutoData]
public void CustomizesDecoratedOrder([BlackFridayOrder(20d)] Order order, Order order1)
{
Assert.Equal(0, order.Tax);
Assert.Equal(20, order.Discount);
Assert.NotEqual(0, order1.Tax);
Assert.NotEqual(20, order1.Discount);
}
}
public class Order
{
public decimal Tax { get; set; }
public decimal Discount { get; set; }
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public class BlackFridayOrderAttribute : Attribute, IParameterCustomizationSource
{
public BlackFridayOrderAttribute(double discount)
{
Discount = (decimal)discount;
}
public decimal Discount { get; }
public ICustomization GetCustomization(ParameterInfo parameter)
{
var builder = Customize<Order>(x => x
.With(x => x.Discount, this.Discount)
.With(x => x.Tax, 0));
return new ParameterRelay(
new ParameterSpecification(
new ExactParameterSpecification(parameter)),
builder)
.ToCustomization();
}
public IPostprocessComposer<T> Customize<T>(Func<IPostprocessComposer<T>, IPostprocessComposer<T>> func)
{
return func(SpecimenBuilderNodeFactory.CreateComposer<T>().WithAutoProperties(true));
}
}
public class ExactParameterSpecification : IEquatable<ParameterInfo>
{
private readonly ParameterInfo parameterInfo;
public ExactParameterSpecification(ParameterInfo parameterInfo)
{
this.parameterInfo = parameterInfo;
}
public bool Equals(ParameterInfo other)
{
return this.parameterInfo?.Equals(other) == true;
}
}
public class ParameterRelay : ISpecimenBuilder
{
private readonly IRequestSpecification specification;
private readonly ISpecimenBuilder builder;
public ParameterRelay(IRequestSpecification specification, ISpecimenBuilder builder)
{
this.specification = specification;
this.builder = builder;
}
public object Create(object request, ISpecimenContext context)
{
if (!this.specification.IsSatisfiedBy(request))
{
return new NoSpecimen();
}
if (request is not ParameterInfo parameter)
return new NoSpecimen();
return this.builder.Create(parameter.ParameterType, context);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment