大发uu快3_uu快3彩票邀请码_大发uu快3彩票邀请码

.net测试篇之测试神器Autofixture Generator使用与自定义builder

时间:2019-09-11 07:04:37 出处:大发uu快3_uu快3彩票邀请码_大发uu快3彩票邀请码

系列目录

有了上一节自定义配置,就说 哪几种的现象都能处理了,后会 机会仅仅是为了处理一个简单哪几种的现象还可不能否 创建一个类显得不得劲繁重.其实AutoFixture在创建Fixture对象时有就说 方便的Fluent配置,亲戚亲戚让我们让我们让我们让我们这里介绍许多比较常用了.

创建对象是忽略许多属性

许多以前一个的许多业务场景,许多字段是非必填项,后会 一旦填写则还可不能否符合指定规则.哪几种非必填字段在业务中仅仅当它指在的以前做许多校验,其它地方并还可不能否 使用到它.一个在单元测试的以前亲戚亲戚让我们让我们让我们让我们为了数率还可不能否暂时忽略哪几种字段.在里面集成测试的以前再提供删剪数据.

下面看看AutoFixture在生成对象的以前如何显式地忽略许多字段

并不一定要忽略是机会机会不忽略AutoFixture自动为字符串类型生成一个guid字符串,这机会原应 验证失败.

亲戚亲戚让我们让我们让我们让我们扩展一下Person类,代码如下

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime BirthDay { get; set; }
        public string Mobile { get; set; }
        public string IDCardNo { get; set; }
        public string Email { get; set; }
    }

亲戚亲戚让我们让我们让我们让我们看配置代码

       [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();

            var psn = fix.Build<Person>().
                Without(a => a.IDCardNo).
                Create();
        }

这里fix对象使用Build辦法 ,生成一个自定义生成对象,之后会老出 就说 自定义配置辦法 ,亲戚亲戚让我们让我们让我们让我们使用without辦法 指示AutoFixture在生成时不生成某一字段,一个without里面还还可不能否再接一个,机会还可不能否忽略其它字段,还可不能否串联使用多个without.

指定当前时间

在集成测试的以前,许多关于时间的字段都需就说 当前时间,这以前还可不能否使用AutoFixture内置的自定义类CurrentDateTimeGenerator来实现

 [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new CurrentDateTimeGenerator());
            var psn = fix.Create<Person>();
        }

[info]当然以上配置机会是还可不能否 必要的,机会C#很早就支持属性赋初值了.

UriGenerator

此配置还可不能否让AutoFixture生成一个Uri

```cs

[Test]

public void FixValueTest()

{

var fix = new Fixture();

fix.Customizations.Add(new UriGenerator());

var br = fix.Create()# AutoFixture配置二

有了上一节自定义配置,就说 哪几种的现象都能处理了,后会 机会仅仅是为了处理一个简单哪几种的现象还可不能否 创建一个类显得不得劲繁重.其实AutoFixture在创建Fixture对象时有就说 方便的Fluent配置,亲戚亲戚让我们让我们让我们让我们这里介绍许多比较常用了.

创建对象是忽略许多属性

许多以前一个的许多业务场景,许多字段是非必填项,后会 一旦填写则还可不能否符合指定规则.哪几种非必填字段在业务中仅仅当它指在的以前做许多校验,其它地方并还可不能否 使用到它.一个在单元测试的以前亲戚亲戚让我们让我们让我们让我们为了数率还可不能否暂时忽略哪几种字段.在里面集成测试的以前再提供删剪数据.

下面看看AutoFixture在生成对象的以前如何显式地忽略许多字段

并不一定要忽略是机会机会不忽略AutoFixture自动为字符串类型生成一个guid字符串,这机会原应 验证失败.

亲戚亲戚让我们让我们让我们让我们扩展一下Person类,代码如下

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime BirthDay { get; set; }
        public string Mobile { get; set; }
        public string IDCardNo { get; set; }
        public string Email { get; set; }
    }

亲戚亲戚让我们让我们让我们让我们看配置代码

       [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();

            var psn = fix.Build<Person>().
                Without(a => a.IDCardNo).
                Create();
        }

这里fix对象使用Build辦法 ,生成一个自定义生成对象,之后会老出 就说 自定义配置辦法 ,亲戚亲戚让我们让我们让我们让我们使用without辦法 指示AutoFixture在生成时不生成某一字段,一个without里面还还可不能否再接一个,机会还可不能否忽略其它字段,还可不能否串联使用多个without.

指定当前时间

在集成测试的以前,许多关于时间的字段都需就说 当前时间,这以前还可不能否使用AutoFixture内置的自定义类CurrentDateTimeGenerator来实现

 [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new CurrentDateTimeGenerator());
            var psn = fix.Create<Person>();
        }

[info]当然以上配置机会是还可不能否 必要的,机会C#很早就支持属性赋初值了.

UriGenerator

此配置还可不能否让AutoFixture生成一个Uri

 [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new UriGenerator());
            var br = fix.Create<Uri>();
        }

MailAddressGenerator

用于生成邮箱地址

 [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new MailAddressGenerator());
            var mr = fix.Create<MailAddress>()
        }

当然就说 以前亲戚亲戚让我们让我们让我们让我们是你要MailAddress里的字符串.这以前使用MailAddress的Address属性即可.

;

}

```

MailAddressGenerator

用于生成邮箱地址

 [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new MailAddressGenerator());
            var mr = fix.Create<MailAddress>()
        }

当然就说 以前亲戚亲戚让我们让我们让我们让我们是你要MailAddress里的字符串.这以前使用MailAddress的Address属性即可.

AutoFixture结合DataAnnotations

许多以前一个许多场影,亲戚亲戚让我们让我们让我们让我们的实体类带有就说 验证注解,这就对制创造创造发明的假数据有就说 要求,比如还可不能否符合邮箱号,身份证号,字符串长度还可不能否为特定值,手机号还可不能否为特定长度数字等等.通过前面讲到的自定义配置亲戚亲戚让我们让我们让我们让我们还可不能否实现以上功能,后会 机会仅仅是为了生成一个指定长度的字符串亲戚亲戚让我们让我们让我们让我们再新建一个配置类其实不得劲繁琐,后会 哪几种逻辑也并不都有通用的.更为复杂性的是有以前一个特定字段还可不能否符合某一正则规则,机会这种 规则非常复杂性你要生成满足它的假数据其实需共要些心思,这以前机会AutoFixture能自动生成满足条件的假数据那该有好多,实际上AutoFixture其实还可不能否生成满足DataAnnotations约束的字段,后会 还可不能否配置默认就说 支持的.

比如现在Person类改为如下:

public class Person{
        [StringLength(10)]
        public string Name { get; set; }
        [Range(18,42)]
        public int Age { get; set; }
        public DateTime BirthDay { get; set; }
        [RegularExpression("\\d{11}")]
        public string Mobile { get; set; }
}

AutoFixture会自动生成满足条件的字段.

AutoFixture 生成符合特定业务的字段.

Attribute自动生成符合注解约束的字段为集成测试提供了很大方便.然而许多功能不论是注解还是AutoFixture内置的配置都无法完成,这以前就还可不能否自定义的配置.

比如说有以下业务场景,许多业务模型带有开使时间和开使时间,这里都一个隐性约束就说 开使时间还可不能否大于机会等于开使时间,机会都一个数据库中就无法取到值.这种 以前就还可不能否使用自定义配置了.

比如有一下模型:

 public class CustomDate
    {
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
    }

[info]这里就说 一个普通例子,就说 以前业务里面都一个的模型,机会要让开使时间晚于开使时间,亲戚亲戚让我们让我们让我们让我们首很难先选则哪个时开使时间,哪个是开使时间,这里亲戚亲戚让我们让我们让我们让我们使用基于命名约束的辦法 来选则它们:即开使时间带有start,开使时间带有end(当然还可不能否是否其它标识,我希望能选则它们即可).当然这并都有五种很好的设计.理想的情况下是对字段进行注解,后会 仅仅为了测试而去扩展现有项目的做法也是值得商榷的.

以下为自定义辦法

 public class DateTimeSpecimenBuilder:ISpecimenBuilder
    {
        private readonly Random _random = new Random();
        private DateTime startDate = DateTime.Now;
        public object Create(object request, ISpecimenContext context)
        {
            var pi = request as PropertyInfo;
            if (pi != null && pi.Name.ToLower().Contains("start") &&
                (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?)))
            {
               
                var stDate = context.Create<DateTime>();
                
                startDate =stDate ;
                return startDate;
            }

            if (pi != null && pi.Name.ToLower().Contains("end") &&
                (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?)))
            {
                var endDate = startDate.AddDays(_random.Next(1,20));
                return endDate;
            }
            return new NoSpecimen();
        }
    }
        [Test]
        public void FixValueTest()
        {
            var fix = new Fixture();
            fix.Customizations.Add(new DateTimeSpecimenBuilder());
            var customDate = fix.Create<CustomDate>();
        }

简单梳理一下以上代码,基本逻辑就说 机会传入字段带有start关键特征后会 是日期类型,亲戚亲戚让我们让我们让我们让我们就把它的值存起来,当里面遇到带有end特征的属性时就把刚才存入的值再去掉 指定天数一个就能保证enddate大于startdate了.

生成引用类型时指定构造函数

当一个类有多个构造函数时,AutoFixture默认使用参数共要的构造函数来构造一个对象,后会 这在许多之后会造成麻烦:一个Bll类机会有多个构造函数,构造函数里传入的是依赖对象,机会只调用参数共要的构造函数则就说 依赖无法传入,一个机会使用到了依赖对象就会报Null引用异常.这种 以前亲戚亲戚让我们让我们让我们让我们就还可不能否显式的指定调用哪一个构造函数.

亲戚亲戚让我们让我们让我们让我们仍然通过示例来讲解.

亲戚亲戚让我们让我们让我们让我们把Person类改成如下:

public class Person
    {
        public Person(string name)
        {
            Name = name;
        }

        public Person(string name,int age)
        {
            Age = age;
            Name = name;
        }
        [StringLength(10)]
        public string Name { get; set; }
        [Range(18,42)]
        public int Age { get; set; }
        public DateTime BirthDay { get; set; }
        [RegularExpression("\\d{11}")]
        public string Mobile { get; set; }
        public string IDCardNo { get; set; }

与以前相比,这种 类多了一个有参构造函数.

注意,即使类型不带是否参构造函数,AutoFixture依然还可不能否创建它,就说 使用哪个构造函数是不选则的.

要实现让AutoFixture选则亲戚亲戚让我们让我们让我们让我们你要的构造函数,亲戚亲戚让我们让我们让我们让我们创建一个实现了IMethodQuery的类型,后会 去掉 到配置里.

这种 类代码如下

 public class MyMethodSelector : IMethodQuery
    {
        private readonly Type[] _types;

        public MyMethodSelector(params Type[] type)
        {
            _types = type;
        }

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

            var constructors = type
                .GetConstructors().Where(a => a.GetParameters().Select(t => t.ParameterType).SequenceEqual(_types))
                .Select(a => new ConstructorMethod(a));

            return constructors;
        }
    }

亲戚亲戚让我们让我们让我们让我们来分析一下这段代码,首先亲戚亲戚让我们让我们让我们让我们在构造函数里传入type 数组,这里的type为构造函数参数的类型.SelectMethods为接口提供的辦法 ,这种 辦法 接收一个type类型作为参数,这种 type为操作的对象的类型.后会 亲戚亲戚让我们让我们让我们让我们使用GetConstructors辦法 获取它所有的构造函数.后会 通过Where过滤符合条件的(条件是参数的类型和构造函数传入的类型一样).后会 亲戚亲戚让我们让我们让我们让我们使用过滤后的Constructorinfo来创建一个ConstructorMethod,ConstructorMethod为AutoFixture提供的一个类型.

下面是测试代码

var fix = new Fixture();
            fix.Customize(new ConstructorCustomization(typeof(Person),
                new MyMethodSelector(typeof(string), typeof(int))));
            var psn = fix.Create<Person>();

这里亲戚亲戚让我们让我们让我们让我们给MyMethodSelector传入了一个类型,分别是string类型和int类型,以期望AutoFixture调用带有string和int参数的构造辦法 .亲戚亲戚让我们让我们让我们让我们启用调试模式,就还可不能否就看Person的第四个构造函数被调用了.

就看这里,就说 人机会会感觉许多厌烦,感觉一个做还不如直接New一个对象,在new的以前显式调用特定的构造函数就不必有还可不能否 麻烦了.关于直接new对象的缺点前面也说过,机会Bll层有变动,则还可不能否显式修改测试辦法 ,不有助维护,后会 这种 辦法 是还可不能否通用的.一旦创建好以前以前遇到一个的业务就还可不能否直接调用了.

热门

热门标签