大发快3_快3高手计划_大发快3高手计划 - 最好的大发快3,快3高手计划,大发快3高手计划平台,QQ技术教程网,分享QQ技巧,网站源码,福利软件,热门视频等各种资源

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

  • 时间:
  • 浏览:0

系列目录

有了上一节自定义配置,所以 大疑问都能除理了,但会 由于仅仅是为了除理另一个 简单大疑问没了创建另一个 类显得不怎么才能 繁重.确实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层有变动,则时需显式修改测试土办法 ,不促使维护,但会 或多或少土办法 是还能否 通用的.一旦创建好时候时候遇到可是我 的业务就还能否 直接调用了.