AutoFixture.AutoMoq supply a known value for one constructor parameter

后端 未结 6 1304
悲哀的现实
悲哀的现实 2020-12-13 14:52

I\'ve just started to use AutoFixture.AutoMoq in my unit tests and I\'m finding it very helpful for creating objects where I don\'t care about the specific

6条回答
  •  春和景丽
    2020-12-13 15:18

    Good thread, I added another twist based on many of the aswers already posted:

    Usage

    Example:

    var sut = new Fixture()
        .For()
        .Set("value1").To(aInterface)
        .Set("value2").ToEnumerableOf(22, 33)
        .Create();
    

    Test classes:

    public class AClass
    {
        public AInterface Value1 { get; private set; }
        public IEnumerable Value2 { get; private set; }
    
        public AClass(AInterface value1, IEnumerable value2)
        {
            Value1 = value1;
            Value2 = value2;
        }
    }
    
    public interface AInterface
    {
    }
    

    Full test

    public class ATest
    {
        [Theory, AutoNSubstituteData]
        public void ATestMethod(AInterface aInterface)
        {
            var sut = new Fixture()
                .For()
                .Set("value1").To(aInterface)
                .Set("value2").ToEnumerableOf(22, 33)
                .Create();
    
            Assert.True(ReferenceEquals(aInterface, sut.Value1));
            Assert.Equal(2, sut.Value2.Count());
            Assert.Equal(22, sut.Value2.ElementAt(0));
            Assert.Equal(33, sut.Value2.ElementAt(1));
        }
    }
    

    Infrastructure

    Extension method:

    public static class AutoFixtureExtensions
    {
        public static SetCreateProvider For(this IFixture fixture)
        {
            return new SetCreateProvider(fixture);
        }
    }
    

    Classes participating in the fluent style:

    public class SetCreateProvider
    {
        private readonly IFixture _fixture;
    
        public SetCreateProvider(IFixture fixture)
        {
            _fixture = fixture;
        }
    
        public SetProvider Set(string parameterName)
        {
            return new SetProvider(this, parameterName);
        }
    
        public TTypeToConstruct Create()
        {
            var instance = _fixture.Create();
            return instance;
        }
    
        internal void AddConstructorParameter(ConstructorParameterRelay constructorParameter)
        {
            _fixture.Customizations.Add(constructorParameter);
        }
    }
    
    public class SetProvider
    {
        private readonly string _parameterName;
        private readonly SetCreateProvider _father;
    
        public SetProvider(SetCreateProvider father, string parameterName)
        {
            _parameterName = parameterName;
            _father = father;
        }
    
        public SetCreateProvider To(TTypeOfParam parameterValue)
        {
            var constructorParameter = new ConstructorParameterRelay(_parameterName, parameterValue);
            _father.AddConstructorParameter(constructorParameter);
            return _father;
        }
    
        public SetCreateProvider ToEnumerableOf(params TTypeOfParam[] parametersValues)
        {
            IEnumerable actualParamValue = parametersValues;
            var constructorParameter = new ConstructorParameterRelay>(_parameterName, actualParamValue);
            _father.AddConstructorParameter(constructorParameter);
            return _father;
        }
    }
    

    Constructor parameter relay from other answers:

    public class ConstructorParameterRelay : ISpecimenBuilder
    {
        private readonly string _paramName;
        private readonly TValueType _paramValue;
    
        public ConstructorParameterRelay(string paramName, TValueType paramValue)
        {
            _paramName = paramName;
            _paramValue = paramValue;
        }
    
        public object Create(object request, ISpecimenContext context)
        {
            if (context == null)
                throw new ArgumentNullException(nameof(context));
            ParameterInfo parameter = request as ParameterInfo;
            if (parameter == null)
                return new NoSpecimen();
            if (parameter.Member.DeclaringType != typeof(TTypeToConstruct) ||
                parameter.Member.MemberType != MemberTypes.Constructor ||
                parameter.ParameterType != typeof(TValueType) ||
                parameter.Name != _paramName)
                return new NoSpecimen();
            return _paramValue;
        }
    }
    

提交回复
热议问题