using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Http.Json; using System.Net; using Newtonsoft.Json; using Microsoft.AspNetCore.Mvc; using System.Text.Json; using System.Security.Authentication.ExtendedProtection; using Newtonsoft.Json.Linq; using System.Text.Json.Serialization.Metadata; namespace HttpClientStudy.UnitTest { /// /// 基础HttpClient 测试 /// public class NormalHttpClientTest { private readonly ITestOutputHelper _logger; public NormalHttpClientTest(ITestOutputHelper outputHelper) { _logger = outputHelper; } #region GET请求 [Fact] public async Task GetAllAccounts_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.GetAsync("/api/Normal/GetAllAccounts"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>>(); Assert.IsType>>(result); Assert.Equal(1, result.Code); Assert.NotNull(result.Data); } /// /// GET 请求 /// (默认参数方式:url传参) /// /// [Fact] public async Task GetAccount_Id_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccount?Id=2"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal(2, result.Data?.Id); } /// /// GET 请求 /// (路由传参) /// /// [Fact] public async Task GetAccount_Route_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccount/管理员02"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal("管理员02", result.Data?.Name); } /// /// GET 请求 /// (中文参数:现在浏览器直接支持,为最大兼容老旧浏览器使用url编码) /// /// [Fact] public async Task GetAccountByName_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var ChineseName = System.Net.WebUtility.UrlEncode("管理员01"); var ChineseName2 = System.Net.WebUtility.UrlEncode("管理员02"); //现在浏览器直接支持中文参数 //var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccountByName?ChineseName=管理员01&ChineseName2=管理员02"); //兼容老浏览器写法 var responseMessage = await httpClient.GetAsync($"/api/Normal/GetAccountByName?ChineseName={ChineseName}&ChineseName2={ChineseName2}"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>>(); Assert.IsType>>(result); Assert.Equal(1, result.Code); Assert.Equal(2, result.Data?.Count); } /// /// GET 请求 /// (查询参数传参) /// /// [Fact] public async Task GetAccountByRole_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccountByRole?role=Admin"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>>(); Assert.IsType>>(result); Assert.Equal(1, result.Code); //每项的角色都是查询的角色 Assert.False(result.Data?.Any(d=>d.Role != "Admin")); } /// /// GET 请求 /// (请求头传参:中文必须Url编码,服务端Url解码后使用) /// /// [Fact] public async Task GetAccountFromHeader_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; //中文参数必须先编码 httpClient.DefaultRequestHeaders.Add("name", System.Net.WebUtility.UrlEncode("管理员01")); var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccountFromHeader"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal(1,result.Data?.Id); } /// /// GET 请求 /// (客户端不传参,服务端参数直接来由IoC中注入的服务) /// /// [Fact] public async Task GetAccountByService_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.GetAsync("/api/Normal/GetAccountFromServices"); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal("服务注入示例",result.Data?.Name); } /// /// GET 请求 /// (直接调用System.Net.Http.Json类的扩展方法GetFromJsonAsync 获取 Json 结果) /// /// [Fact] public async Task Get_From_Json_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var result = await httpClient.GetFromJsonAsync>("/api/Normal/GetAccountFromServices"); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal("服务注入示例", result.Data?.Name); } #endregion #region PUT 请求 /// /// Put 请求 /// (新建或替换、更新资源) /// /// [Fact] public async Task PutDemo_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var responseMessage = await httpClient.PutAsync("/api/Normal/PutDemo?id=2",null); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadAsStringAsync(); } #endregion #region HEAD 请求 /// /// Head 请求 /// 注意:HttpClient没有直接提供HEAD请求方法: /// 步骤1:构建 HttpRequestMessage 对象,设置HttpMethod.Head /// 步骤2:把上步构建的HttpRequestMessage 对象,作为参数传递给 HttpClient实例的 Send 或 SendAsync 方法 /// /// [Fact] public async Task HeadDemo_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var requestMessage = new HttpRequestMessage(HttpMethod.Head, "/api/Normal/HeadDemo?Id=2"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); //head请求没有返回体 var result = await responseMessage.Content.ReadAsStringAsync(); Assert.Empty(result); } #endregion #region POST 请求 [Fact] public async Task PostSimple_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; //响应 var responseMessage = await httpClient.PostAsync("/api/Normal/PostSimple", null); //响应正常 Assert.True(responseMessage.IsSuccessStatusCode); Assert.NotNull(responseMessage); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result?.Code); } [Fact] public async Task PostCreate_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; //参数 var para = new Account() {Id=100, Name="小明", Password="123456", Role="Admin" }; //请求体 var plainContent = new StringContent(JsonConvert.SerializeObject(para), Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json); //发POST请求 var responseMessage = await httpClient.PostAsync("/api/Normal/PostCreate", plainContent); //确保响应正常 responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var text = await responseMessage.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject (text); Assert.IsType(result); Assert.Equal(201, result.StatusCode); Assert.IsType(result.Value); //新创建的对象 var account = JsonConvert.DeserializeObject(value: result.Value.ToString() ?? ""); Assert.NotNull(account); Assert.Equal(100,account.Id); //由于构造函数等原因,直接使用ReadFromJsonAsync,会异常。 //CreatedAtActionResult? result = await responseMessage.Content.ReadFromJsonAsync(new JsonSerializerOptions() { IncludeFields=true, PropertyNameCaseInsensitive=true}); } [Fact] public async Task PostUpdate_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; //参数 var para = new Account() { Id = 1, Name = "小明", Password = "123456", Role = "Admin" }; //发POST请求 var responseMessage = await httpClient.PostAsJsonAsync("/api/Normal/PostUpdate", para); //确保响应正常 responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal(1, result.Data?.Id); } [Fact] public async Task PostRemove_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var para_id = 2; //发POST请求(URL传参) var responseMessage = await httpClient.PostAsync($"/api/Normal/PostRemove?Id={para_id}", null); //确保响应正常 responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal(para_id, result.Data?.Id); } #endregion #region DELETE 请求 [Fact] public async Task Delete_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var para_id = 2; //发POST请求(URL传参) var responseMessage = await httpClient.DeleteAsync($"/api/Normal/Delete?Id={para_id}"); //确保响应正常 responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); Assert.Equal(para_id, result.Data); } [Fact] public async Task Delete2_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; //Delete 默认不使用请求体,如果使用的话,需要Content配合 RequestMessage var account = new Account() { Id = 2, Name = "小明", Password = "123456", Role = "Admin" }; var requestMessage = new HttpRequestMessage(HttpMethod.Delete, "/api/Normal/DeleteForJsonData"); //requestMessage.Content = JsonContent.Create(account); //也可以下面的,极少有使用(可自定义JsonSerializerOptions) //requestMessage.Content = JsonContent.Create(account,JsonTypeInfo.CreateJsonTypeInfo( JsonSerializerOptions.Default),new System.Net.Http.Headers.MediaTypeHeaderValue("application/json","utf-8")); //发POST请求(URL传参) var responseMessage = await httpClient.SendAsync(requestMessage); //确保响应正常 responseMessage.EnsureSuccessStatusCode(); Assert.NotNull(responseMessage); Assert.True(responseMessage.IsSuccessStatusCode); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result.Code); } #endregion #region OPTIONS 请求 [Fact] public async Task OPTIONS_Test() { HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(TestConfig.WebApiBaseUrl), }; var requestMessage = new HttpRequestMessage(HttpMethod.Options, "/api/Normal/OptionsSimple"); //响应 var responseMessage = await httpClient.SendAsync(requestMessage); //响应正常 Assert.True(responseMessage.IsSuccessStatusCode); Assert.NotNull(responseMessage); var result = await responseMessage.Content.ReadFromJsonAsync>(); Assert.IsType>(result); Assert.Equal(1, result?.Code); } #endregion #region PATCH 请求 #endregion #region TRACE 请求 #endregion #region CONNECT 请求 #endregion } }