日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

使用Microsoft.AspNetCore.TestHost进行完整的功能测试

發(fā)布時(shí)間:2023/12/4 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Microsoft.AspNetCore.TestHost进行完整的功能测试 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)介

Microsoft.AspNetCore.TestHost是可以用于Asp.net Core 的功能測(cè)試工具。很多時(shí)候我們一個(gè)接口寫好了,單元測(cè)試什么的也都o(jì)k了,需要完整調(diào)試一下,檢查下單元測(cè)試未覆蓋到的代碼是否有bug。步驟為如下:程序打個(gè)斷點(diǎn)->F5運(yùn)行->通常需要登錄個(gè)測(cè)試賬號(hào)->查找要調(diào)試api的入口->獲得斷點(diǎn)開(kāi)始調(diào)試=>代碼報(bào)錯(cuò)?很多時(shí)候需要停止調(diào)試修改->回到第一步。如此反復(fù)循環(huán),做著重復(fù)的工作,Microsoft.AspNetCore.TestHost正是為了解決這個(gè)問(wèn)題,它可以讓你使用xTest或者M(jìn)STest進(jìn)行覆蓋整個(gè)HTTP請(qǐng)求生命周期的功能測(cè)試。

進(jìn)行一個(gè)簡(jiǎn)單的功能測(cè)試

新建一個(gè)Asp.net Core WebApi和xUnit項(xiàng)目

ValuesController里面自帶一個(gè)Action

我們?cè)趚Unit項(xiàng)目里面模擬訪問(wèn)這個(gè)接口,首選安裝如下nuget包:

  • Microsoft.AspNetCore.TestHost

  • Microsoft.AspNetCore.All(很多依賴懶得找的話直接安裝這個(gè)集成包,百分之90涉及到AspNetCore的依賴都包含在里面)

然后需要引用被測(cè)試的AspnetCoreFunctionalTestDemo項(xiàng)目,新建一個(gè)測(cè)試類ValuesControllerTest

將GetValuesTest方法替換為如下代碼,其中startup類是應(yīng)用自AspnetCoreFunctionalTestDemo項(xiàng)目


? ? ? ?[Fact] ? ? ? ?public void GetValuesTest(){ ? ? ? ? ? ?var client = new TestServer(WebHost.CreateDefaultBuilder().UseStartup<Startup>()).CreateClient(); ? ? ? ? ? ?string result = client.GetStringAsync("api/values").Result;Assert.Equal(result, JsonConvert.SerializeObject(new string[] { "value1", "value2" }));}


此時(shí)在ValueController打下斷點(diǎn)

?

運(yùn)行GetValuesTest調(diào)試測(cè)試

成功進(jìn)入斷點(diǎn),我們不用啟動(dòng)瀏覽器,就可以進(jìn)行完整的接口功能測(cè)試了。

修改內(nèi)容目錄與自動(dòng)授權(quán)

上面演示了如何進(jìn)行一個(gè)簡(jiǎn)單的功能測(cè)試,但是存在兩個(gè)缺陷:

  • webApi在測(cè)試的時(shí)候?qū)嶋H的運(yùn)行目錄是在FunctionalTest目錄下

  • 對(duì)需要授權(quán)的接口不能正常測(cè)試,會(huì)得到未授權(quán)的返回結(jié)果

  • ?1.內(nèi)容目錄

    我們可以在Controller的Get方法輸出當(dāng)前的內(nèi)容目錄

    內(nèi)容目錄是在測(cè)試x項(xiàng)目下這與我們的預(yù)期不符,如果webapi項(xiàng)目對(duì)根目錄下的文件有依賴關(guān)系例如appsetting.json則會(huì)找不到該文件,解決的辦法是在webHost中手動(dòng)指定運(yùn)行根目錄

    [Fact]public void GetValuesTest() { ? ?var client = new TestServer(WebHost.CreateDefaultBuilder() ? ? ? ?.UseContentRoot(GetProjectPath("AspnetCoreFunctionalTestDemo.sln", "", typeof(Startup).Assembly)).UseStartup<Startup>()).CreateClient(); ? ?string result = client.GetStringAsync("api/values").Result;Assert.Equal(result, JsonConvert.SerializeObject(new string[] { "value1", "value2" })); }/// <summary>/// 獲取工程路徑/// </summary>/// <param name="slnName">解決方案文件名,例test.sln</param>/// <param name="solutionRelativePath">如果項(xiàng)目與解決方案文件不在一個(gè)目錄,例如src文件夾中,則傳src</param>/// <param name="startupAssembly">程序集</param>/// <returns></returns>

    private static string GetProjectPath(string slnName, string solutionRelativePath, Assembly startupAssembly) { ? ? ?string projectName = startupAssembly.GetName().Name; ? ? ?string applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath; ? ? ?var directoryInfo = new DirectoryInfo(applicationBasePath); ? ? ?do{ ? ? ? ? ?var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, slnName)); ? ? ? ? ?if (solutionFileInfo.Exists){ ? ? ? ? ? ? ?return Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath, projectName));}directoryInfo = directoryInfo.Parent;} ? ? ?while (directoryInfo.Parent != null); ? ? ?throw new Exception($"Solution root could not be located using application root {applicationBasePath}.");
    }

    ?GetProjectPath方法采用遞歸的方式找到startup的項(xiàng)目所在路徑,此時(shí)我們?cè)龠\(yùn)行

    2.自動(dòng)授權(quán)

    每次測(cè)試時(shí)手動(dòng)登錄這是一件很煩人的事情,所以我們希望可以自動(dòng)話,這里演示的時(shí)cookie方式的自動(dòng)授權(quán)

    首先在startup文件配置cookie認(rèn)證

    namespace AspnetCoreFunctionalTestDemo { ?
    ? ??
    public class Startup{ ? ? ?
    ? ? ? ? ? ?
    public Startup(IConfiguration configuration){Configuration = configuration;} ? ?

    ? ? ? ?
    public IConfiguration Configuration { get; } ? ? ? ?// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddMvc(); ? ? ? ? ?
    ??services.AddAuthentication(o
    => o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o =>{o.ExpireTimeSpan = new TimeSpan(0, 0, 30);o.Events.OnRedirectToLogin = (context) =>{context.Response.StatusCode = 401; ? ? ? ? ? ? ? ? ? ? ? return Task.CompletedTask;};}); ? ? ? ?} ? ? ? ?// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){ ? ? ? ? ? ?if (env.IsDevelopment()){app.UseDeveloperExceptionPage();} ? ? ? ? ? ?app.UseAuthentication();app.UseMvc();}} }


    這里覆蓋了cookie認(rèn)證失敗的默認(rèn)操作改為返回401狀態(tài)碼。

    在valuesController新增登錄的Action并配置Get的Action需要授權(quán)訪問(wèn)

    namespace AspnetCoreFunctionalTestDemo.Controllers {[Route("api/[controller]")] ?
    ?
    public class ValuesController : Controller{ ? ? ? ?

    // GET api/values ? ? ?
    ? ? ? ?[HttpGet,Authorize] ? ?
    ? ? ? ?
    public IEnumerable<string> Get([FromServices]IHostingEnvironment env){ ? ? ? ? ? ?

    return new string[] { "value1", "value2" };} ? ? ?
    ?
    // POST api/values[HttpGet("Login")] ?
    ? ? ?
    public void Login(){ ? ? ? ? ?
    ??
    var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);identity.AddClaim(new Claim(ClaimTypes.Name, "huanent")); ? ? ? ? ? ?var principal = new
    ClaimsPrincipal(identity);HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal).Wait();}} }

    此時(shí)我們使用測(cè)試項(xiàng)目測(cè)試Get方法

    如我們預(yù)期,返回了401,說(shuō)明未授權(quán)。我們修改下GetValuesTest


    namespace FunctionalTest { ?
    ?
    public class ValuesControllerTest{[Fact] ? ? ?
    ??
    public void GetValuesTest(){ ? ? ? ? ?
    ??
    var client = new TestServer(WebHost.CreateDefaultBuilder().UseStartup<Startup>().UseContentRoot(GetProjectPath("AspnetCoreFunctionalTestDemo.sln", "", typeof(Startup).Assembly))).CreateClient(); ? ? ? ?
    ? ?
    var respone = client.GetAsync("api/values/login").Result;SetCookie(client, respone); ? ? ? ? ? ?var result = client.GetAsync("api/values").Result;} ? ? ? ?private static void SetCookie(HttpClient client, HttpResponseMessage respone){ ? ? ? ? ? ?string cookieString = respone.Headers.GetValues("Set-Cookie").First(); ? ? ? ? ? ?string cookieBody = cookieString.Split(';').First();client.DefaultRequestHeaders.Add("Cookie", cookieBody);} ? ? ?
    ?
    /// <summary>/// 獲取工程路徑 ? ? ?
    ??
    /// </summary>/// <param name="slnName">解決方案文件名,例test.sln</param>/// <param name="solutionRelativePath">如果項(xiàng)目與解決方案文件不在一個(gè)目錄,例如src文件夾中,則傳src</param>/// <param name="startupAssembly">程序集</param>/// <returns></returns>private static string GetProjectPath(string slnName, string solutionRelativePath, Assembly startupAssembly){ ? ? ? ? ?
    ?
    string projectName = startupAssembly.GetName().Name; ? ? ? ? ?
    ??
    string applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath; ? ? ? ?
    ? ?
    var directoryInfo = new DirectoryInfo(applicationBasePath); ? ? ? ?
    ? ?
    do{ ? ? ? ? ? ? ?
    var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, slnName)); ? ? ? ? ? ?
    ?? ?
    if (solutionFileInfo.Exists){ ? ? ? ? ? ? ? ? ?
    ??
    return Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath, projectName));}directoryInfo = directoryInfo.Parent;} ? ? ? ? ?
    ??
    while (directoryInfo.Parent != null); ? ? ?
    ? ? ?
    throw new Exception($"Solution root could not be located using application root {applicationBasePath}.");}} }


    我們首先訪問(wèn)api/Values/Login,獲取到Cookie,然后講cookie附在httpclient的默認(rèn)http頭上,這樣就能夠成功訪問(wèn)需要授權(quán)的接口了

    總結(jié)

    通過(guò)上面演示,我們已經(jīng)可以很大程度地模擬了整個(gè)api請(qǐng)求,讓我們可以方便地一鍵調(diào)試目標(biāo)接口,再也不用開(kāi)瀏覽器或postman了。

    附上演示項(xiàng)目地址:https://github.com/huanent/AspnetCoreFunctionalTestDemo

    原文:http://www.cnblogs.com/huanent/p/7886282.html


    .NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com

    總結(jié)

    以上是生活随笔為你收集整理的使用Microsoft.AspNetCore.TestHost进行完整的功能测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。