.net core集成測試之Post請求
Web項目中,很多與用戶數據交互的請求都是Post請求,想必大家都用過HttpClient構造過post請求,這里並不對HttpClient做詳細介紹,只介紹一些常用的功能.並結合AutoFixture演示如何自動構造請求數據,簡單手動創建Json或者Formdata的工作量,提高生產效率.
我們為上節創建的HelloWorld控制器添加一個StudentInfo方法,內容如下
[HttpPost]
public IActionResult StudentInfo(Student student)
{
return Content(student.Name);
}
這個方法的參數是一個Student類型的對象,和早期版本mvc並沒有太大差別,我們把這個Student類的代碼貼出來:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public byte Gender { get; set; }
public string School { get; set; }
}
下面我們來構造一個對StudentInfo的請求測試方法.
如何創建測試內存服務器的方法在第8節里有講到,這里不再講,以下用到的都是測試服務器創建的
HttpClient對象.
[Fact]
public async Task SimplePost()
{
Dictionary<string, string> dict = new Dictionary<string, string>
{
{"name","sto"},
{"age","32" },
{"gender","2" },
{"school","middleschool" }
};
var response = await _client.PostAsync("/HelloWorld/StudentInfo", new FormUrlEncodedContent(dict));
response.EnsureSuccessStatusCode();
var result =await response.Content.ReadAsStringAsync();
Assert.Equal("sto", result);
}
以上代碼可能大家都非常熟悉了.我們用dictionary對象構造了formdata然后做為post請求內容發送到服務端,服務端返回的是接收到的student對象的name屬性,這里我們驗證服務端返回的name是不是我們傳過去的"sto".
然而這樣做是非常耗時的,如果只寫一兩個測試方法還好,對成千上百個方法這樣構建參數是非常繁瑣和乏味的,並且如果后端對數據有限制的情況下想構造出來符合條件的數據更是麻煩,並且后端接口如果字段有修改則有可能造成測試失敗.由於測試項目引用了mvc項目,因此我們可以訪問到mvc項目里的這些類型,然后使用AutoFixture動態創建這些類型的實例,然后序列化為Json提交,這樣會明顯減少工作量並增加程序的可維護性.
AutoFixture的安裝前面也提到過,並且它是支持.net core的,我們在Nuget包管理工具界面輸入AutoFixture.Xunit2進行搜索,然后下載這個包即可,如果直接下載它則不用下載AutoFixture包,因為它是這個包的一個依賴,會自動安裝.
改造后的方法如下:
[Theory]
[AutoData]
public async Task SimplePost(Student stud)
{
var content = new StringContent(JsonConvert.SerializeObject(stud), Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/HelloWorld/StudentInfo", content);
response.EnsureSuccessStatusCode();
var result =await response.Content.ReadAsStringAsync();
Assert.True(!string.IsNullOrEmpty(result));
}
首先fact注解變成了Theory注解,我們知道要為測試方法添加參數需要使用Theory注解,下面添加了AutoData注解,添加以后AutoFixture就會自動為方法的參數提供值.
下面我們把stud對象序列化為json字符串,然后包裝成一個stringcontent對象提交到后台,由於傳入的是什么值是AutoFixture隨機創建的,我們並不知道,因此不能像上面一樣斷言它是"sto",但是它一定是有值的,因此我們斷言它不是null或者空字符串.
然而遺憾的是,以上測試卻沒有通過,我們看一下錯誤面板信息:

通過面板信息我們看到AutoFixture構建的對象Name里是有值的,然而卻返回的False,我們只知道結果,其中的過程我們並不清楚,也很難直觀的看到錯誤原因,這時候我們使用調試模式來啟動測試程序
首先我們在測試方法剛進入的時候打上斷點,看看傳入的有沒有值

進入mvc項目,在方法剛進入的地方也打上斷點

下面我們對測試方法執行調試
測試方法如何調試在前面的章節中已經講過,我們在Test Explorer面板里找到這個方法然后右鍵點擊它的名字,在右鍵菜單里選擇"調試單元測試",更為簡單的方法是,如果一個測試方法執行失敗,則在它的方法定義上會出現一個紅叉

我們點擊這個紅叉就會出現一個浮動面板

下面有兩個按鈕一個是運行一個是調試,點擊調試就可以進入調試模式了.
第一個斷點處我們看到stud的每一個字段都是有值的

按下F5繼續,進入mvc方法里的斷點

我們看到這里每個字段綁定的都是默認值,也就是我們傳入的值並沒有綁定成功.
以上的調試是為了展示如何調試mvc測試項目,以上單步調試並不能幫助我們太多,其實是因為.net core mvc改變了以往的綁定方式,改成了webapi 2.0的綁定方式,也就是要顯式的給參數加上FromBody注解方可成功綁定json數據
前面的示例我們看到formData是不需要注解就可以成功綁定的
我們改一下Mvc里的方法,增加一個frombody注解
[HttpPost]
public IActionResult StudentInfo([FromBody]Student student)
{
return Content(student.Name);
}
我們再次運行,就能夠正確綁定值了.
注意,很多人會想,是不是加了frombody注解以后即能夠接收formdata類型的參數,又能接收json類型參數呢,其實答案是否定的,如果加上了frombody后再提供formdata類型參數,則會返回415不支持的格式錯誤.因此這里要權衡,如果是傳統的mvc項目通過form提交,則不能添加frombody,當然有一些插件可以把form序列化為json,這樣就可以了.
有引起朋友可能會有疑惑,我直接從瀏覽器發送請求或者使用postman工具就行了,干嘛這么費勁呢?這樣做的意義何在呢?其實前面也說到過,使用postman或者其它工具請求一方面不利於自動化測試(當然,postman是可以做到的)另一方面這樣做依賴於外部web服務器,如果有多個環境在發布更新的時候遺漏了某一個環境就會造成測試結果的不穩定,並且測試環境遷移了,測試項目也要跟着遷移,增加了維護成本.使用asp.net core自身的內存web服務器功能則完全不依賴於外部web服務器或者外部測試工具,測試時自動啟動web服務器,測試完成自己銷毀,極大地方便了持續測試.
