系列目录html
实际工做中咱们须要的数据逻辑万千,变幻无穷,而AutoFixture默认是按照必定算法随机生成一些假数据,虽然这在多数时候是ok的,可是可能不能知足咱们的全部业务场景,有些时候咱们须要进行一些配置,以期达到指定目标.算法
前面我介首先介绍的是AutoFixture如何与Nunit结合提供测试数据,这里咱们介绍一下它自身,即脱离Nunit时它是如何工做起来的.服务器
这里主要用到的就是Fixture对象的Create
看如下代码dom
[Test] public void FixValueTest() { var fix = new Fixture(); var str = fix.Create<string>(); }
经过以上代码,咱们就可能建立一个string类型的对象,其它对象也是如法炮制.函数
下面咱们来解决上一节中遗漏的一个问题,就是如何在建立集合的时候显式的指定个数.测试
其实也很简单,那就是在建立Fixture对象的时候指定一个RepeatCount,这样就能够生成指定数量的集合啦.ui
代码改成以下code
[Test] public void FixValueTest() { var fix = new Fixture {RepeatCount = 10}; var str = fix.Create<IEnumerable<string>>(); }
就能够生成一个包含10个String元素的集合.htm
不少时候咱们并非简单的建立一个字符串或者数字,而是建立一个对象,不少时候咱们要是对这些对象进行验证的,若是随机生成一些可能没法经过验证,咱们下面介绍如何按照必定的规则生成一个对象.
好比说咱们要生成一个Person对象,服务器对Person的Name是要约束的,不能包含特定符号和阿拉伯数字,而AutoFixture自动生成的则是Guid转成的字符字符串,而且长度也不符合姓名规则.
下面咱们看一下如何生成一个例规的姓名.
[Test] public void FixValueTest() { var s = GetString(5); var fix = new Fixture(); fix.Customizations.Add(new StringGenerator(() => s)); var person= fix.Create<Person>(); } string GetString(int count) { List<int> ints = new List<int>(); Random rand = new Random(); for (int i = 0; i < count; i++) { int value = rand.Next(97 ,122); ints.Add(value); } var charArr = ints.Select(Convert.ToChar).ToArray(); var str = string.Concat(charArr); return str; }
这里咱们自定义了一个算法,生成一个字符串,而后在fix配置里的自定义配置里面添加一个StringGenerator自定义配置类(这个类是框架带的),它接收一个委托.这样咱们就能够获得期待的字符串了.
咱们把测试代码改成以下
[Test] public void FixValueTest() { var fix = new Fixture(); fix.Customizations.Add(new StringSpecimenBuilder()); var person= fix.Create<Person>(); }
这里的StringSpecimenBuilder是咱们自定义的,它实现了ISpecimenBuilder接口,咱们看下代码
public class StringSpecimenBuilder:ISpecimenBuilder { private readonly int _strLenCount; public StringSpecimenBuilder(int strLenCount=5) { _strLenCount = strLenCount; } public object Create(object request, ISpecimenContext context) { var property = request as PropertyInfo; if (property != null && property.Name == "Name" && property.PropertyType == typeof(string)) return GetString(_strLenCount); return new NoSpecimen(); } string GetString(int count) { List<int> ints = new List<int>(); Random rand = new Random(); for (int i = 0; i < count; i++) { int value = rand.Next(97, 122); ints.Add(value); } var charArr = ints.Select(Convert.ToChar).ToArray(); var str = string.Concat(charArr); return str; } }
其中的GetString咱们刚才用到过,这里把它移到这里来.
咱们来分析下这段代码,构造函数里咱们接收一个int类型变量,用于自定义生成字符串的长度.
下面的Create方法为从接口里实现来的方法.
它的第一个参数request为要建立的对象,对于咱们的Person类来讲,它要建立这个类和类里的全部属性,每个属性都是一个request对象.下面的代码咱们判断请求对象是不是属性,若是是而且属性名是Name而且属性类型为string,那么咱们就返回算法获得的值,不然返回NoSpecimen,返回NoSpecimen表示不使用自定义的算法.
经过以上配置生成的name就能符合咱们的需求了.
[info]在集成测试过程当中咱们还能够对省市县等数据创建起列表,而后动态自定义填充.
以上咱们判断属性名是不是Name条件过严,咱们能够适当放宽一些,则能适应的场景更广.