如何测试 ASP.NET Core Web API
在本文中,我們將研究如何測試你的 ASP .NET Core 2.0 Web API 解決方案。我們將了解使用單元測試進(jìn)行內(nèi)部測試,使用全新的 ASP .NET Core 的集成測試框架來進(jìn)行外部測試。
本文要點(diǎn)
正確理解并使用單元測試和你的 ASP .NET Core Web API 解決方案一樣重要。
了解并使用模擬數(shù)據(jù)進(jìn)行單元測試可以幫助你獲得穩(wěn)定的測試場景。
為 ASP .NET Core Web API 解決方案在 .NET Core 2.1 中創(chuàng)建模擬數(shù)據(jù)項(xiàng)目。
了解并設(shè)置集成測試來從外部測試 API,這樣可以幫助完整測試 ASP .NET Core 2.1 Web API 解決方案。
.NET Core 最初是在 2016 年發(fā)布的,隨著 .NET Core 2.0 的發(fā)布,微軟擁有了下一個(gè)通用、模塊化、跨平臺(tái)和開源的平臺(tái)主版本。.NET Core 已經(jīng)創(chuàng)建了許多 API,在當(dāng)前版本的 .net 框架中均可用。它最初是為下一代 ASP .NET 解決方案而創(chuàng)建的,但現(xiàn)在成了許多其他場景的驅(qū)動(dòng)和基礎(chǔ),包括物聯(lián)網(wǎng)、云計(jì)算和下一代移動(dòng)解決方案。在本系列文章中,我們將探討 .NET Core 的一些好處,以及它如何不僅能使傳統(tǒng)的 .NET 開發(fā)人員受益,還能使所有需要為市場帶來健壯、高效和經(jīng)濟(jì)的解決方案的技術(shù)人員受益。
在使用 ASP .NET Core 2.1 Web API 構(gòu)建并開發(fā)一組豐富的 API 的時(shí)候,需要記住這只是實(shí)現(xiàn)穩(wěn)定且高效的解決方案的第一步。為你的解決方案提供一個(gè)穩(wěn)定的環(huán)境是非常重要的。獲得優(yōu)秀的解決方案不僅需要完整地構(gòu)建 API,還需要嚴(yán)格地測試你的 API,保證用戶有良好的體驗(yàn)。
這篇文章是我之前為 InfoQ 寫的《針對(duì) ASP.NET Core Web API 的先進(jìn)架構(gòu)》的后續(xù)文章。請(qǐng)放心,你不需要閱讀另外一篇文章,就可以從這篇文章了解到如何從測試中獲得好處,但讀一下那篇文章可以幫助你更多了解我是如何構(gòu)建我討論的解決方案的。在過去的幾年里,我花了大量時(shí)間來思考在為客戶構(gòu)建 API 時(shí)進(jìn)行測試。了解 ASP .NET Core 2.1 Web API 的架構(gòu),可以幫助拓寬你的了解。
本篇文章中的例子的解決方案和所有代碼都可以在我的GitHub 庫中找到。
ASP .NET Core Web API 快速入門
讓我們一起來快速了解一下 .NET 和 ASP .NET Core。ASP .NET Core 是 Microsoft 創(chuàng)造的全新 Web 框架,以便擺脫自 ASP .NET 1.0 以來一直存在的遺留技術(shù)。ASP .NET Core 2.1 擺脫這些遺留依賴,從頭開始開發(fā)框架,因此可以給開發(fā)人員提供更高的性能,并且它是為跨平臺(tái)執(zhí)行而構(gòu)建的。
什么是單元測試?
對(duì)有些人來說,測試你的軟件可能是一個(gè)新的概念,但是它很簡單。我們從單元測試開始。維基百科對(duì)于它的嚴(yán)格定義是“是一種軟件測試方法,對(duì)源代碼的獨(dú)立單元、一組或多組計(jì)算機(jī)程序模塊以及相關(guān)的控制數(shù)據(jù)、使用程序和操作程序都進(jìn)行測試,以了解它們是否適合使用”。我比較喜歡的是一個(gè)外行的解釋,單元測試是保證在你添加了新的功能或進(jìn)行了缺陷修復(fù)之后,你的解決方案中的代碼能像預(yù)期一樣執(zhí)行。我們測試了一個(gè)簡單的代碼示例,來保證它符合我們的預(yù)期。讓我們來看一下單元測試示例:
復(fù)制代碼
[]
public async Task AlbumGetAllAsync()
{
// Arrange
// Act
var albums = await _repo.GetAllAsync();
// Assert
Assert.Single(albums);
}
優(yōu)秀的單元測試有三個(gè)部分組成。第一個(gè)是Arrange的部分,用來設(shè)置測試中可能需要的任何資源。在上面的例子中,我沒有進(jìn)行任何設(shè)置,所以 Arrange 的部分是空的 (但我還是為它保留了注釋)。第二個(gè)部分是Act的部分,用來執(zhí)行測試的部分。在我們的例子中,我調(diào)用數(shù)據(jù)庫中的專輯實(shí)體類型,返回當(dāng)前使用的庫中的數(shù)據(jù)源完整的專輯實(shí)體。單元測試的最后一個(gè)部分是Assert的部分,用來驗(yàn)證待測試的操作是否正確。對(duì)于該測試,我檢驗(yàn)是否從數(shù)據(jù)庫中返回了一個(gè)專輯。
在本文中,我會(huì)使用 xUnit 工具進(jìn)行單元測試。xUnit 是 .NET Framework 和現(xiàn)在的 .NET Core 的開源包。我們需要 .NET Core 版本的 xUnit,在你安裝 .NET Core 2.1 SDK 的時(shí)候就已經(jīng)直接獲得了。你可以通過 .NET Core cli 指令 dotnet test,或是通過你喜歡的 IDE(如 Visual Studio 2017、Visual Studio Code 或 JetBrain 的 Rider.)中的項(xiàng)目模板來創(chuàng)造新的單元測試項(xiàng)目。
圖 1:在 Visual Studio 2017 中創(chuàng)建新的單元測試項(xiàng)目
現(xiàn)在,讓我們深入到測試你的 ASP .NET Core Web API 解決方案的單元測試中來。
Web API 要單元測試一些什么?
我非常支持使用單元測試來為你的客戶保證穩(wěn)定和健壯的 API。但我清楚地知道要如何使用單元測試,知道要測試什么東西。我相信,你要恰到好處地對(duì)解決方案進(jìn)行單元測試,而不要做多余的測試。這是什么意思呢?可能我的觀點(diǎn)會(huì)引發(fā)很多評(píng)論,但是我不太注重要 100% 覆蓋你的測試。我是否認(rèn)為我們需要能覆蓋 API 解決方案重要部分的測試,單獨(dú)隔開每個(gè)區(qū)域,保證每個(gè)代碼段都是正確的?當(dāng)然!我會(huì)這么做,這也是我想要討論的。
由于我們的示例 Chinook.API 很小,并且可以通過集成測試來完成測試(本文稍后討論),我發(fā)現(xiàn)在 Domain 和 Data 項(xiàng)目中我最關(guān)注單元測試。我不會(huì)詳細(xì)討論單元測試的方法(因?yàn)檫@個(gè)問題超出了本文討論的范圍)。我想要讓你不依賴于生產(chǎn)數(shù)據(jù)庫的數(shù)據(jù),從而在 Domain 和 Data 項(xiàng)目中進(jìn)行更多的測試。這是我們下一個(gè)要討論的問題,模擬數(shù)據(jù)和對(duì)象。
為什么在單元測試中使用模擬數(shù)據(jù)和對(duì)象?
我們已經(jīng)討論了為什么我們要進(jìn)行單元測試,單元測試一些什么內(nèi)容。接下來,了解如何準(zhǔn)確地單元測試 ASP .NET Core Web API 解決方案是非常重要的。數(shù)據(jù)是測試 API 的重點(diǎn)。測試可預(yù)測的數(shù)據(jù)集是非常重要的。這就是為什么我不推薦使用生產(chǎn)數(shù)據(jù)或者其他可能隨著時(shí)間根據(jù)你的了解和認(rèn)知會(huì)改變的數(shù)據(jù)。我們需要穩(wěn)定的數(shù)據(jù)集來保證所有單元測試的運(yùn)行,確保代碼段之間的測試是相同的。比如說,在我測試 Chinook.Domain 項(xiàng)目的時(shí)候,我想要得到 ID 是 42 的專輯,我需要保證它的確存在,并擁有類似專輯名稱這樣的細(xì)節(jié),和一條藝術(shù)家數(shù)據(jù)有關(guān)聯(lián)關(guān)系。我還希望確保在我從數(shù)據(jù)源中得到一系列專輯時(shí),大小滿足我編寫的單元測試。
許多業(yè)內(nèi)人士使用“模擬數(shù)據(jù)”這一術(shù)語來表示這一類數(shù)據(jù)。有很多為單元測試產(chǎn)生模擬數(shù)據(jù)的方法,我希望你能創(chuàng)造出盡可能“真實(shí)”的數(shù)據(jù)集。你給測試創(chuàng)造的數(shù)據(jù)越好,測試效果也會(huì)越好。我會(huì)建議你確保數(shù)據(jù)沒有隱私問題,不包含公司或客戶的個(gè)人數(shù)據(jù)或敏感數(shù)據(jù)。
要滿足我們對(duì)于干凈、穩(wěn)定數(shù)據(jù)的需求,我單獨(dú)創(chuàng)建了一個(gè)項(xiàng)目,封裝了單元測試項(xiàng)目的模擬數(shù)據(jù)。讓我們稱其為 Chinook.MockData(就像你能在示例中看到的一樣)。我的 MockData 項(xiàng)目幾乎和 Chinook.Data 項(xiàng)目相同。它們都擁有相同數(shù)量的數(shù)據(jù)庫,都和相同的接口依附。我希望 MockData 項(xiàng)目存儲(chǔ)在依賴注入 (DI) 容器中,這樣 Chinook.Domain 項(xiàng)目就可以像連接到了生產(chǎn)數(shù)據(jù)源那樣得到使用。這就是為什么我很喜歡依賴注入。它可以幫助我通過配置切換 Data 項(xiàng)目,而不需要做任何代碼變更。
集成測試:什么是針對(duì) Web API 的新測試?
在我們?yōu)?ASP .NET Core Web API 解決方案執(zhí)行并驗(yàn)證了單元測試之后,我們要看一個(gè)完全不同類型的測試。我希望單元測試可以驗(yàn)證并確保對(duì)解決方案內(nèi)部組件的期望。當(dāng)我們對(duì)內(nèi)部測試的質(zhì)量滿意的時(shí)候,我們需要從外部接口進(jìn)行 API 測試,這就是我們所說的集成測試。
集成測試需要在所有的組件完成的時(shí)候編寫并執(zhí)行,所以你的 API 可以通過正確的 HTTP 響應(yīng)來驗(yàn)證。單元測試時(shí)測試的是單獨(dú)隔離開的代碼段,而集成測試時(shí)測試的是 HTTP 端點(diǎn)上每個(gè) API 的整體邏輯。測試將會(huì)遵循 API 的完整工作流,從 API 項(xiàng)目的控制器到域項(xiàng)目管理器,最后到 Data 項(xiàng)目的庫(返回來響應(yīng))。
創(chuàng)造集成測試項(xiàng)目
要使用你現(xiàn)有的測試知識(shí),集成測試功能是基于現(xiàn)有的單元測試庫的。我將使用 xUnit 來創(chuàng)造我的集成測試。在我們創(chuàng)建了名為 Chinook.IntegrationTest 的新 xUnit 測試項(xiàng)目之后,我們需要添加合適的 NuGet 包。將 Microsoft.AspNetCore.TestHost 包添加到 Chinook.IntegrationTest 項(xiàng)目中來。這個(gè)包中包含了執(zhí)行集成測試的資源。
圖 2:添加 Microsoft.AspNetCore.TestHost NuGet 包
接下來,我們可以創(chuàng)建第一個(gè)集成測試來從外部驗(yàn)證我們的 API。
創(chuàng)建第一個(gè)集成測試
要想進(jìn)行我們解決方案中的所有 API 外部測試,我要?jiǎng)?chuàng)建一個(gè)名為 API 的文件夾,其中包含了測試。我還需要在 API 域中給每個(gè)實(shí)體類型創(chuàng)建新的測試類。我們的首個(gè)集成測試將會(huì)覆蓋專輯實(shí)體類型。
在 API 文件夾中創(chuàng)建新的類 AlbumAPITest.cs。之后我們會(huì)在文件中添加如下的命名空間。
復(fù)制代碼
using Xunit;
using Chinook.API;
using Microsoft.AspNetCore.TestHost;
using Microsoft.AspNetCore.Hosting;
圖 3:使用指令進(jìn)行集成測試
現(xiàn)在我們要使用 TestServer 來設(shè)置類,使用 HttpClient 來執(zhí)行測試。我們需要名為 _client,類型為 HttpClient 的私有變量,它是基于在 AlbumAPITest 類中的構(gòu)造函數(shù)中初始化的 TestServer 而創(chuàng)建的。TestServer 是小型 web 服務(wù)器的包裝器,是基于 Chinook.API Startup 和需要的開發(fā)環(huán)境創(chuàng)建的。在這個(gè)例子中,我使用開發(fā)環(huán)境。我們現(xiàn)在具備了運(yùn)行 API 的 web 服務(wù)器,以及了解如何在 TestServer 中調(diào)用 API 的客戶端。我們可以開始編寫集成測試代碼了。
圖 4:我們第一個(gè)集成測試,獲得所有的專輯
除了構(gòu)造函數(shù)代碼之外,圖 4 中還展示了第一個(gè)集成測試的代碼。AlbumGetAllTestAsync 方法將會(huì)測試驗(yàn)證從 API 獲取所有專輯的調(diào)用。就像之前討論的單元測試一樣,集成測試的邏輯也是用了 Arrange、Act 和 Assert。我們首先創(chuàng)建 HttpRequestMessage 對(duì)象,其中 HTTP 作為 InlineData 注釋中的變量而提供,URI 部分表示對(duì)于所有的專輯的調(diào)用 (“/api/Album/”)。之后我們會(huì)讓 HttpClient _client 發(fā)送 HTTP 請(qǐng)求,最后,我們會(huì)檢查驗(yàn)證 HTTP 響應(yīng)是否滿足我們的期望,在本例中是 200。圖 4 中我展示了兩種檢驗(yàn) API 調(diào)用的方法。你可以使用其中任意一種,但我更喜歡第二種方法,因?yàn)樗试S我用相同的模式來檢驗(yàn)對(duì)特定 HTTP 響應(yīng)代碼的響應(yīng)。?
response.EnsureSuccessStatusCode();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
我們還可以創(chuàng)建需要從 API 測試特定實(shí)體鍵的集成測試。對(duì)于這類測試,我們需要在 InlineData 注釋中添加額外的值,將會(huì)通過 AlbumGetTestAsync 方法參數(shù)傳遞。我們的新測試會(huì)使用相同的邏輯,并使用和之前測試一樣的資源,但是我們?yōu)?HttpRequestMessage 對(duì)象在 API URI 端中傳遞實(shí)體鍵。你可以在圖 5 中查看代碼。
圖 5:專輯的第二個(gè)集成測試
在你為測試 API 創(chuàng)造了所有集成測試之后,需要通過 Test Runner 來運(yùn)行它們,并保證它們?nèi)客ㄟ^。你創(chuàng)建的所有測試也可以在 DevOps 持續(xù)集成(CI)過程中執(zhí)行,這樣可以在整體開發(fā)和部署過程中測試你的 API。現(xiàn)在需要有執(zhí)行路徑保證你的 API 在開發(fā)、質(zhì)量保證和部署階段都得到測試和維護(hù),讓你的 API 使用者擁有良好體驗(yàn)的同時(shí)不發(fā)生意外情況。
圖 6:在 Visual Studio 2017 中運(yùn)行集成測試
結(jié)論
擁有良好設(shè)計(jì)的一套測試計(jì)劃,使用單元測試來做內(nèi)部測試,使用集成測試來驗(yàn)證 API 調(diào)用就和開發(fā) ASP .NET Core Web API 階段創(chuàng)建架構(gòu)是一樣重要的。
本文作者
Chris Woodruff?(Woody)?擁有密歇根州立大學(xué)工程學(xué)院的計(jì)算機(jī)科學(xué)學(xué)位。Woody 已經(jīng)開發(fā)和架構(gòu)軟件解決方案超過 20 年,并且曾經(jīng)致力于許多不同的平臺(tái)和工具。他是一個(gè)社區(qū)領(lǐng)袖,為 GRDevNight、GRDevDay、West Michigan Day of .NET 和 CodeMash 之類的活動(dòng)貢獻(xiàn)過力量。他還幫助把廣受歡迎的 Give Camp 活動(dòng)帶到西密歇根,那里的技術(shù)專業(yè)人士提供他們的時(shí)間和發(fā)展專業(yè)知識(shí),以幫助當(dāng)?shù)氐姆菭I利組織。作為一個(gè)演講者和播客作者,Woody 演講和討論過很多話題,包括數(shù)據(jù)庫設(shè)計(jì)和開源。他在 Visual C#、數(shù)據(jù)平臺(tái)和 SQL 方面一直是微軟的 MVP,并在 2010 年被公認(rèn)為全球最優(yōu)秀的 20 個(gè) MVPs 之一。Woody 是 JetBrains 的開發(fā)者,并且在北美推廣 .NET、.NET Core 和 JetBrains 的產(chǎn)品。
.NET Core 最初是在 2016 年發(fā)布的,隨著 .NET Core 2.0 的發(fā)布,微軟擁有了一個(gè)通用、模塊化、跨平臺(tái)和開源的平臺(tái)主版本。.NETCore 已經(jīng)創(chuàng)建了許多 API,在當(dāng)前版本的 .net 框架中均可用。它最初是為下一代 ASP .NET 解決方案而創(chuàng)建的,但現(xiàn)在成了許多其他場景的驅(qū)動(dòng)和基礎(chǔ),包括物聯(lián)網(wǎng)、云計(jì)算和下一代移動(dòng)解決方案。在本系列文章中,我們將探討 .NET Core 的一些好處,以及它如何不僅能使傳統(tǒng)的 .NET 開發(fā)人員受益,還能使所有需要為市場帶來健壯、高效和經(jīng)濟(jì)的解決方案的技術(shù)人員受益。
原文地址:https://www.infoq.cn/article/4Z59Jy7ptKNERdv-o8Qp
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的如何测试 ASP.NET Core Web API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EFCore+Mysql仓储层建设(分页
- 下一篇: .NET Core中的一个接口多种实现的