Specifying [readonly] property values [via ctor args] when instantiating [immutable] objects with AutoFixture

后端 未结 3 1654
予麋鹿
予麋鹿 2020-12-17 22:10

My test requires that I set the Response property on an immutable Rsvp object (see below) to a specific value.

public class Rsvp
{
         


        
3条回答
  •  一生所求
    2020-12-17 23:05

    Extending Nikos´ answer, we can generalize the customization to work with any property as such:

    public class OverridePropertyBuilder : ISpecimenBuilder
    {
        private readonly PropertyInfo _propertyInfo;
        private readonly TProp _value;
    
        public OverridePropertyBuilder(Expression> expr, TProp value)
        {
            _propertyInfo = (expr.Body as MemberExpression)?.Member as PropertyInfo ??
                            throw new InvalidOperationException("invalid property expression");
            _value = value;
        }
    
        public object Create(object request, ISpecimenContext context)
        {
            var pi = request as ParameterInfo;
            if (pi == null)
                return new NoSpecimen();
    
            var camelCase = Regex.Replace(_propertyInfo.Name, @"(\w)(.*)",
                m => m.Groups[1].Value.ToLower() + m.Groups[2]);
    
            if (pi.ParameterType != typeof(TProp) || pi.Name != camelCase)
                return new NoSpecimen();
    
            return _value;
        }
    }
    

    But then we need custom extension methods to make it easier to use:

    public class FixtureCustomization
    {
        public Fixture Fixture { get; }
    
        public FixtureCustomization(Fixture fixture)
        {
            Fixture = fixture;
        }
    
        public FixtureCustomization With(Expression> expr, TProp value)
        {
            Fixture.Customizations.Add(new OverridePropertyBuilder(expr, value));
            return this;
        }
    
        public T Create() => Fixture.Create();
    }
    
    public static class CompositionExt
    {
        public static FixtureCustomization For(this Fixture fixture)
            => new FixtureCustomization(fixture);
    }
    

    we then use it in your example as:

    var obj = 
      new Fixture()
        .For()
        .With(x => x.Response, "Attending")
        .Create();
    

提交回复
热议问题