系列目錄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條件過嚴,咱們能夠適當放寬一些,則能適應的場景更廣.