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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

【ASP.NET Core 沉思录】CreateWebHostBuilder 是一个 Convension

發(fā)布時間:2023/12/4 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【ASP.NET Core 沉思录】CreateWebHostBuilder 是一个 Convension 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

失蹤人口回歸。去年六月份開始,我開始翻譯一千多頁的《CSharp 7 in a Nutshell》到現在為止終于告一段落。我又回歸了表世界。從這次開始我希望展開一個全新的主題。我叫它 ASP.NET Core 沉思錄(多么高大上的名字,自我陶醉~)。今天是第一個主題。CreateWebHostBuilder 是一個 Convension。

太長不讀

對于 WebApplicationFactory<T> 而言,默認情況下會采取如下假定:

  • Startup 所在的程序集應當就是應用程序入口(Main)所在的程序集;(官方工程模板的坑)

  • 應用程序入口所在的類(Program),里面會包含整個創(chuàng)建和配置 IWebHostBuilder 的過程;

  • 創(chuàng)建和配置 IWebHostBuilder 的過程是由應用程序入口所在類的 CreateWebHostBuilder 方法完成的。

在滿足上述假定的情況下,無需額外代碼,Web 應用的執(zhí)行和測試將共享相同的邏輯。如若不然,則測試失敗。如果無法滿足上述三種條件還可以通過集成 WebApplicationFactory<T> 并重寫 CreateWebHostBuilder 方法來解決。

以上約束僅僅限定于 WebApplicationFactory<T>,若直接在測試中使用 TestServer 則沒有這種限制。

WebApplicationFactory<T> 的 T 并不是 TStartup,而是應用程序入口所在的程序集中的任意類型。

娓娓道來

如果我們使用 dotnet 命令行創(chuàng)建一個 ASP.NET Core MVC/WebAPI 的工程。那么它的啟動代碼大概是這樣的:

public?static?class?Program
{
????public?static?void?Main(string[]?args)
????
{
????????CreateWebHostBuilder(args).Build().Run();
????}

????public?static?IWebHostBuilder?CreateWebHostBuilder(string[]?args)
????
{
????????//?Modified?a?little?bit?for?the?sake?of?illustration
????????return?new?WebHostBuilder()
????????????.UseKestrel()
????????????.ConfigureLogging(lb?=>
????????????{
????????????????lb.SetMinimumLevel(LogLevel.Debug).AddConsole();
????????????})
????????????.UseStartup<Startup>();
????}
}

有沒有小伙伴好奇,為什么需要一個 CreateWebHostBuilder 方法?從直觀上看,它是創(chuàng)建并完成基本的 IWebHostBuilder 配置的方法。這個方法應在測試中進行復用以確保測試和應用程序中的 IWebHostBuilder 配置幾乎相同,例如:

[Fact]
public?async?Task?should_get_response_text()
{
????IWebHostBuilder?webHostBuilder?=?Program.CreateWebHostBuilder(Array.Empty<string>());

????using?(var?testServer?=?new?TestServer(webHostBuilder))
????using?(HttpClient?client?=?testServer.CreateClient())
????{
????????HttpResponseMessage?response?=?await?client.GetAsync("/message");

????????Assert.Equal(HttpStatusCode.OK,?response.StatusCode);
????????Assert.Equal("Hello",?await?response.Content.ReadAsStringAsync());
????}
}

這個測試是可以順利通過的。但是我們認為將 Program.CreateWebHostBuilder 暴露并不是一個好的感覺。我們更希望把這個配置過程分離。例如分離到一個類中:

public?class?WebHostBuilderConfigurator
{
????public?IWebHostBuilder?Configure(IWebHostBuilder?webHostBuilder)
????
{
????????return?webHostBuilder
????????????.UseKestrel()
????????????.ConfigureLogging(lb?=>
????????????{
????????????????lb.SetMinimumLevel(LogLevel.Debug).AddConsole();
????????????})
????????????.UseStartup<Startup>();
????}
}

這樣,Program 僅僅包含整個應用程序的入口,CreateWebHostBuilder 方法就被刪掉了:

public?static?void?Main(string[]?args)
{
????var?webHostBuilder?=?new?WebHostBuilder();
????new?WebHostBuilderConfigurator().Configure(webHostBuilder).Build().Run();
}

測試也就變成了:

[Fact]
public?async?Task?should_get_response_text()
{
????IWebHostBuilder?webHostBuilder?=?new?WebHostBuilderConfigurator().Configure(new?WebHostBuilder());

????using?(var?testServer?=?new?TestServer(webHostBuilder))
????using?(HttpClient?client?=?testServer.CreateClient())
????{
????????HttpResponseMessage?response?=?await?client.GetAsync("/message");

????????Assert.Equal(HttpStatusCode.OK,?response.StatusCode);
????????Assert.Equal("Hello",?await?response.Content.ReadAsStringAsync());
????}
}

看起來不錯,測試也通過了真是可喜可賀。現在我們準備使用更加完善的 WebApplicationFactory<T> 代替 TestServer 進行測試:

[Fact]
public?async?Task?should_get_response_text_using_web_app_factory()
{
????using?(var?factory?=?new?WebApplicationFactory<Startup>().WithWebHostBuilder(
????????wb?=>?new?WebHostBuilderConfigurator().Configure(wb)))
????using?(HttpClient?client?=?factory.CreateClient())
????{
????????HttpResponseMessage?response?=?await?client.GetAsync("/message");

????????Assert.Equal(HttpStatusCode.OK,?response.StatusCode);
????????Assert.Equal("Hello",?await?response.Content.ReadAsStringAsync());
????}
}

看起來不錯,但是發(fā)現測試運行的時候卻失敗了。并伴有詭異的異常信息:

System.InvalidOperationException?:?No?method?'public?static?IWebHostBuilder?CreateWebHostBuilder(string[]?args)'?found?on?'WebApp.Program'.?Alternatively,?WebApplicationFactory`1?can?be?extended?and?'protected?virtual?IWebHostBuilder?CreateWebHostBuilder()'?can?be?overridden?to?provide?your?own?IWebHostBuilder?instance.

哦,真神奇,它怎么找到 WebApp.Program 的?我只告訴了它 Startup 而并沒有提供任何 Program 類型的信息啊?而這個時候,如果我們老老實實的恢復 WebApp.Program 類中的 CreateWebHostBuilder 方法,那么測試就順利通過了。

這是為什么呢?原來讓測試環(huán)境盡可能的 Match 執(zhí)行環(huán)境是我們共同的心愿,WebApplicationFactory 希望能夠自動的幫我們解決這個問題,于是它做了如下的假定:

  • Startup 所在的程序集應當就是應用程序入口(Main)所在的程序集;

  • 應用程序入口所在的類(Program),里面會包含整個創(chuàng)建和配置 IWebHostBuilder 的過程;

  • 創(chuàng)建和配置 IWebHostBuilder 的過程是由應用程序入口所在類的 CreateWebHostBuilder 方法完成的。

只要符合這三個假定,那么你盡可不費吹灰之力就達到了產品測試配置一致的目的。而如果不符合這個假定將讓測試在默認狀態(tài)下執(zhí)行失敗。具體的代碼請參考 這里 和 這里。從 WebHostFactoryResolver 里面可以看出,除了 CreateWebHostBuilder 方法之外,BuildWebHost 也是一個 Convension,只不過主要是為了向前兼容的目的。

在真實的項目中,很可能是不滿足這三個條件的,那么怎么辦呢?還好我們可以通過集成 WebApplicationFactory<T> 并重寫 CreateWebHostBuilder 方法來解決這個問題:

public?class?MyWebApplicationFactory?:?WebApplicationFactory<Startup>
{
????protected?override?IWebHostBuilder?CreateWebHostBuilder()
????
{
????????var?webHostBuilder?=?new?WebHostBuilder();
????????new?WebHostBuilderConfigurator().Configure(webHostBuilder);
????????return?webHostBuilder;
????}
}

并相應的將測試更改為:

[Fact]
public?async?Task?should_get_response_text_using_web_app_factory()
{
????using?(var?factory?=?new?MyWebApplicationFactory())
????using?(HttpClient?client?=?factory.CreateClient())
????{
????????HttpResponseMessage?response?=?await?client.GetAsync("/message");

????????Assert.Equal(HttpStatusCode.OK,?response.StatusCode);
????????Assert.Equal("Hello",?await?response.Content.ReadAsStringAsync());
????}
}

就可以了。

最后,需要提醒的是 WebApplicationFactory<T> 的 T 是 TEntryPoint ,是入口所在的程序集的類型。雖然平常大家都喜歡寫 Startup。

總結

請飛到文章開頭~ :-D


總結

以上是生活随笔為你收集整理的【ASP.NET Core 沉思录】CreateWebHostBuilder 是一个 Convension的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产黄色片在线观看 | 国产乱淫av麻豆国产免费 | 极品白嫩的小少妇 | www.四虎影视.com | 色综合激情| 日本理论片午伦夜理片在线观看 | 91射| 亚洲精品乱码久久久久久不卡 | 精品无码黑人又粗又大又长 | 日韩精品久久久久久久的张开腿让 | 免费在线观看成人 | 国产免费资源 | 免费一级特黄毛大片 | va在线观看 | 性xxxx视频播放免费 | 欧美日韩色视频 | 亚洲国产精品视频一区 | 国产成人精品综合久久久久99 | 涩涩视频网址 | 男同av在线观看一区二区三区 | 理论片大全免费理伦片 | 午夜剧场91 | 在线免费一区二区 | 东京热毛片 | 欧美日韩中文字幕在线 | 国产情侣呻吟对白高潮 | 日鲁鲁 | 日韩欧美99| 亚洲欧美日韩精品永久在线 | 国产午夜亚洲精品午夜鲁丝片 | 女人一级一片30分 | 日韩在线观看 | 高清毛片aaaaaaaaa片 | 校园春色欧美 | 做爰无遮挡三级 | 日本三级中文 | 超碰在线成人 | 欧美日本在线 | 91视频国产免费 | 中文在线亚洲 | 91精品小视频 | 日本视频免费看 | 麻豆欧美 | 樱桃视频污污 | av片一区二区 | 免费无遮挡无码永久在线观看视频 | 91波多野结衣 | a级片在线视频 | 国产古装艳史毛片hd | 夜夜爱夜夜操 | 韩国三级视频 | 一区二区免费在线视频 | 成人在线看片 | 欧美性猛交xx乱大交 | 性免费网站 | 成人永久免费视频 | 欧美最黄视频 | 在线一二区 | 茄子视频A | 亚洲免费视频播放 | 国产精品vip | 嫩草午夜少妇在线影视 | 自偷自拍av| 毛片库| 亚洲一区二区三区黄色 | 尤物视频免费观看 | 天美麻花果冻视频大全英文版 | 九九视屏 | 在线免费观看av片 | 青青草视频免费观看 | 国产精品性 | 国产成人超碰人人澡人人澡 | 久久综合久久鬼 | 黑人巨大精品一区二区在线 | 免费黄色网址视频 | 成人av网址在线 | 成人网入口 | 自拍偷拍亚洲精品 | 制服 丝袜 激情 欧洲 亚洲 | 欧美人体一区二区三区 | 在线不卡日韩 | 日韩av专区片 | 在线观看麻豆 | 九九热中文字幕 | 91色片| 高清国产视频 | 求一个黄色网址 | 黄色不雅视频 | av一区二区不卡 | 97视频在线免费观看 | 国产精品资源网 | a√在线 | 欧美精品性生活 | 亚洲在线观看免费视频 | 欧美大片一级 | 草草浮力影院 | 日韩av一卡二卡 | 亚洲色图少妇 | 爱情岛论坛亚洲品质自拍视频 |