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

  • 时间:
  • 浏览:1
  • 来源:幸运快3_快3最新版_幸运快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层有变动,则还要显式修改测试法律土办法,不有有助于于维护,咋样让 这俩法律土办法是可不可不可以 通用的.一旦创建好以前以前遇到原先 的业务就可不可不可以 直接调用了.