ASP.NET Core 中做集成测试的三种方案
學(xué)習(xí)·進(jìn)步
老張的哲學(xué)
不定期更新的
日常
? 在平時(shí)的開發(fā)中,我們很少會(huì)關(guān)注到測試的問題,更別說集成測試了,除非是公司有硬性要求或者是自己的開源項(xiàng)目中,為了整體架構(gòu)的完整性,需要用測試來做輔助點(diǎn)綴,而更多的也僅僅是單元測試(說的就是我自己????),最近在寫書的時(shí)候才進(jìn)一步考慮到這一點(diǎn),如何在一個(gè)ASP.NET Core框架中,引入集成測試呢?
??這里我結(jié)合這三年開源的經(jīng)驗(yàn),總結(jié)了一些心得,給大家分享一下,如果有更好的建議,歡迎在評論區(qū)進(jìn)行留言喲。
PS:單元測試就不說了,比較簡單,最多就是依賴注入和MOCK的問題,不會(huì)的話也可以留言。
方案一:萬物皆可Mock
? 在軟件測試當(dāng)中,我們經(jīng)常,甚至是到處都會(huì)用到mock來處理對象實(shí)例化的問題,在單元測試中,mock十分常見,畢竟是為了測試一個(gè)小模塊,其他的就不需要考慮,直接mock就行了,如果在集成測試的時(shí)候,如何測試接口呢,比如BlogController如何使用?我在blog.core項(xiàng)目中,就是這么使用到的,示例代碼如下:
Mock<IBlogArticleServices> mockBlogSev = new Mock<IBlogArticleServices>();Mock<ILogger<BlogController>> mockLogger = new Mock<ILogger<BlogController>>();BlogController blogController;private IBlogArticleServices blogArticleServices;DI_Test dI_Test = new DI_Test();public BlogController_Should(){mockBlogSev.Setup(r => r.Query());var container = dI_Test.DICollections();blogArticleServices = container.Resolve<IBlogArticleServices>();blogController = new BlogController(mockLogger.Object);}? 說句實(shí)話,這并非是集成測試,這種寫法可能比較低端,通過mock配合new,創(chuàng)建了控制器,然后調(diào)用接口,看起來不是很高大上,而且集成測試本來就是要測試整體性,不能把所有的參數(shù)都mock吧。同時(shí)官方好像也說過,不要到處使用mock。
而且,這種方案,也要考慮如何使用依賴注入的問題!
所以這種方案做集成測試我給:
??
方案二:實(shí)例化TestServer對象
? 這種是比較常見的,也是微軟官方架構(gòu)項(xiàng)目eShopOnContainers的推薦方案,簡單來說,就是微軟提供了一個(gè)TestSever的類,為我們提供一個(gè)類似WebHost的宿主服務(wù)器,只不過是測試服務(wù)器,那如何測試Controller控制器呢,示例代碼如下:
public TestServer CreateServer(){var path = Assembly.GetAssembly(typeof(CatalogScenariosBase)).Location;var hostBuilder = new WebHostBuilder().UseContentRoot(Path.GetDirectoryName(path)).ConfigureAppConfiguration(cb =>{cb.AddJsonFile("appsettings.json", optional: false).AddEnvironmentVariables();}).UseStartup<Startup>();var testServer = new TestServer(hostBuilder);testServer.Host.MigrateDbContext<CatalogContext>((context, services) =>{var env = services.GetService<IWebHostEnvironment>();var settings = services.GetService<IOptions<CatalogSettings>>();var logger = services.GetService<ILogger<CatalogContextSeed>>();new CatalogContextSeed().SeedAsync(context, env, settings, logger).Wait();}).MigrateDbContext<IntegrationEventLogContext>((_, __) => { });return testServer;}? 可以看到,通過new TestServer()的方式,生成一個(gè)服務(wù)器,就可以發(fā)起請求了,核心的還是我們的WebHostBuilder。
至于如何調(diào)用就更簡單了,直接對server發(fā)起HttpClient請求即可:
? 這種是很簡單的,而且也不用考慮mock的問題,畢竟用的直接就是web項(xiàng)目的WebHost宿主機(jī)Builder來構(gòu)建的。
? 但是有一個(gè)很致命的問題,我們在.NET5以后,使用Autofac做依賴注入的容器,而且ConfigureServices也是沒有返回值的,這樣在使用上面的TestServer,就會(huì)報(bào)錯(cuò),提示找不到Autofac服務(wù)。
? 但是如果你查看eShopOnContainers的源碼后,就知道他們還是將ConfigureServices做了返回值處理:
public IServiceProvider ConfigureServices(IServiceCollection servic{// 自定義服務(wù)擴(kuò)展services.AddAppInsight(Configuration)// and so on....AddCustomMVC(Configuration);// 使用Autofac依賴注入容器var container = new ContainerBuilder();container.Populate(services);return new AutofacServiceProvider(container.Build());}? 如果你能接受這種依賴注入的方式的話,也是可以使用這種方案的,這是一個(gè)注意點(diǎn),要知道。
所以這種方案做集成測試我給:
????
方案三:使用.UseTestServer()
? 除了上面的這種方式,還有一種方式,也是官方提供的,比較類似,也是通過創(chuàng)建宿主機(jī)服務(wù)器的形式,不過是新的HostBuilder的ConfigureWebHostDefaults方式創(chuàng)建的,示例代碼如下:
public static IHostBuilder GetTestHost() {return new HostBuilder()//替換autofac作為DI容器.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseTestServer().UseStartup<Startup>();}).ConfigureAppConfiguration((host, builder) =>{builder.SetBasePath(Directory.GetCurrentDirectory());builder.AddJsonFile("appsettings.json", optional: true);builder.AddEnvironmentVariables();}); }? 既然上面說了我們不能單獨(dú)處理自定義容器,我們就和之前一樣,指定就好,設(shè)計(jì)思路和我們的WebApi中的Program.cs特別像,然后使用起來就更加簡單了:
using var server = await ArticleScenariosBase.GetTestHost().StartAsync();// Action 發(fā)起接口請求var response = await server.GetTestClientWithToken().GetAsync("/api/blogs?page=1&pageSize=5");// Assert 確保接口狀態(tài)碼是200response.EnsureSuccessStatusCode();? 這種方案不僅兼容了第二種方案的優(yōu)點(diǎn),而且對之前我們設(shè)計(jì)的Autofac依賴注入容器沒有做任何的修改。
所以這種方案做集成測試我給:
?????
編者按:Blog.Core開源三周年
【原料】
?個(gè)人開源項(xiàng)目Blog.Core馬上就已經(jīng)開源三周年了,經(jīng)過許許多多的小伙伴功能努力的結(jié)果,希望給ASP.NET Core在國內(nèi)的推廣,提供一個(gè)落地級別的案例。
【制法】
?A、累計(jì)提交上千次Commit;
?B、配合前、后、認(rèn)證、鑒權(quán)一體化方案;
?C、不完全統(tǒng)計(jì),被60+公司使用中;
【調(diào)味】
1.希望更多的小伙伴參與并提交PR。
2.希望更多的公司和組織使用,提供寶貴生產(chǎn)意見。
3.希望可以得到組織的孵化,讓項(xiàng)目更進(jìn)一步,有意者可以聯(lián)系我。
Tips: 九月新內(nèi)容,敬請期待。
HAPPY EVEY DAY!
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core 中做集成测试的三种方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国唯一一位女性 Apache Memb
- 下一篇: 一文读懂 .NET 中的高性能队列 Ch