Integration testing
Integration testing
集成測試用來確保app的不同模塊之間可以正確的一起工作。ASP.NET Core提供單元測試框架和內(nèi)建的測試網(wǎng)絡服務來支持集成測試,并且測試網(wǎng)絡服務不需要網(wǎng)絡開銷就可以處理請求。
View or download sample code
Introduction to integration testing
不像單元測試,集成測試通常包含app的基礎設施問題,比如,數(shù)據(jù)庫,文件系統(tǒng),網(wǎng)絡資源,網(wǎng)絡請求和響應。單元測試使用假的或模擬的對象來代替這些問題,但是集成測試的目的是確認系統(tǒng)在這些基礎設施之上是否能正常的運行。
集成測試,運行更大量的代碼段,并且因為他們依賴于基礎設施元素,往往比單元測試慢幾個數(shù)量級。因此,限制編寫的集成測試數(shù)量是個好主意,尤其是當你可以使用單元測試來測試相同的行為。
Note
如果一些行為可以使用單元測試或集成測試來測試,請使用單元測試,因為它幾乎總是更快。 您可能有許多或幾百個單元測試與許多不同的輸入,但只是一些覆蓋最重要的場景的集成測試。
不需要寫太多的集成測試來確認你能夠?qū)懭牒妥x取數(shù)據(jù)到數(shù)據(jù)庫。不需要列舉每一個可能的組合,只需要確認app可以一起正常工作就可以。
Integration testing ASP.NET Core
要設置好集成測試并運行,需要創(chuàng)建一個測試項目,添加需要測試的項目的ASP.NET Core網(wǎng)站應用,并安裝一個測試運行器。這個過程在Unit testing有描述。
Note
將單元測試和集成測試分成不同的項目,將幫助你避免意外的將基礎架構(gòu)問題引入單元測試,并且可以很容易的選擇啟動哪一組測試。
The Test Host
ASP.NET Core包含一個測試主機,可以添加到集成測試項目,并用于托管ASP.NET Core應用程序,提供測試請求,而不需要真正的Web主機。
所提供的示例包括已配置為使用xUnit和測試主機的集成測試項目。 它使用Microsoft.AspNetCore.TestHost NuGet包。
一旦Microsoft.AspNetCore.TestHost包包含在項目中,您就可以在測試中創(chuàng)建和配置TestServer。 以下測試顯示如何驗證對網(wǎng)站根目錄發(fā)出的請求返回“Hello World!”。 并應成功運行由Visual Studio創(chuàng)建的ASP.NET Core的默認空Web模板。
public class PrimeWebDefaultRequestShould {private readonly TestServer _server;private readonly HttpClient _client;public PrimeWebDefaultRequestShould(){// Arrange_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());_client = _server.CreateClient();}[Fact]public async Task ReturnHelloWorld(){// Actvar response = await _client.GetAsync("/");response.EnsureSuccessStatusCode();var responseString = await response.Content.ReadAsStringAsync();// AssertAssert.Equal("Hello World!",responseString);} }此測試使用Arrange-Act-Assert模式。 Arrange步驟在構(gòu)造函數(shù)中完成,它創(chuàng)建一個TestServer的實例。 一個配置好的WebHostBuilder將用于創(chuàng)建TestHost; 在此示例中,來自被測系統(tǒng)(SUT)的Startup類的Configure方法被傳遞給WebHostBuilder。 此方法將用于配置TestServer的請求管道,與SUT服務器的配置方式相同。
在測試的Act部分,向TestServer實例發(fā)出“/”路徑的請求,并將響應讀回到字符串中。 此字符串與預期的“Hello World!”字符串進行比較。 如果它們匹配,則測試通過; 否則失敗。
現(xiàn)在,您可以添加一些額外的集成測試,以確認素數(shù)檢查功能能在app中正常運行。
public class PrimeWebCheckPrimeShould {private readonly TestServer _server;private readonly HttpClient _client;public PrimeWebCheckPrimeShould(){// Arrange_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());_client = _server.CreateClient();}private async Task<string> GetCheckPrimeResponseString(string querystring = ""){var request = "/checkprime";if(!string.IsNullOrEmpty(querystring)){request += "?" + querystring;}var response = await _client.GetAsync(request);response.EnsureSuccessStatusCode();return await response.Content.ReadAsStringAsync();}[Fact]public async Task ReturnInstructionsGivenEmptyQueryString(){// Actvar responseString = await GetCheckPrimeResponseString();// AssertAssert.Equal("Pass in a number to check in the form /checkprime?5",responseString);}[Fact]public async Task ReturnPrimeGiven5(){// Actvar responseString = await GetCheckPrimeResponseString("5");// AssertAssert.Equal("5 is prime!",responseString);}[Fact]public async Task ReturnNotPrimeGiven6(){// Actvar responseString = await GetCheckPrimeResponseString("6");// AssertAssert.Equal("6 is NOT prime!",responseString);} }注意!!!上面的集成測試不是用來檢查素數(shù)檢查器的正確性的,而是檢查app是否像你期望的那樣運行,因為素數(shù)檢查器的正確性是單元測試覆蓋的范圍。
Refactoring to use middleware
重構(gòu)是改變應用程序代碼以改進其設計而不改變其行為的過程。 理想情況下,有一套已經(jīng)通過的測試,可以幫助確保系統(tǒng)的行為在更改之前和之后保持不變。 查看在Web應用程序的Configure方法中實現(xiàn)主要檢查邏輯的方式,您將看到:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Run(async (context) =>{if (context.Request.Path.Value.Contains("checkprime")){int numberToCheck;try{numberToCheck = int.Parse(context.Request.QueryString.Value.Replace("?", ""));var primeService = new PrimeService();if (primeService.IsPrime(numberToCheck)){await context.Response.WriteAsync($"{numberToCheck} is prime!");}else{await context.Response.WriteAsync($"{numberToCheck} is NOT prime!");}}catch{await context.Response.WriteAsync("Pass in a number to check in the form /checkprime?5");}}else{await context.Response.WriteAsync("Hello World!");}}); }這個代碼可以正常運行,但它遠不是你想要實現(xiàn)的那樣,即使這么簡單。 想象一下,如果你需要在每次添加另一個URL路徑時都添加這么多的代碼,Configure方法會是什么樣子?
一個選項是考慮在app中添加MVC,創(chuàng)建一個控制器來處理素數(shù)的檢查。然而,假設你現(xiàn)在不需要MVC的其他功能,因為它太大了。
可以利用ASP.NET Core middleware,它可以讓我們再自己的類中封裝素數(shù)檢查邏輯,并讓Configure方法更好的分離關(guān)注點。
您希望允許中間件使用路徑作為參數(shù),因此中間件類在其構(gòu)造函數(shù)中需要一個RequestDelegate和一個PrimeCheckerOptions實例。 如果請求的路徑與此中間件配置的不匹配,您只需調(diào)用鏈中的下一個中間件,不做任何進一步操作。 配置中的其余實現(xiàn)代碼現(xiàn)在位于Invoke方法中。
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using PrimeWeb.Services; using System; using System.Threading.Tasks;namespace PrimeWeb.Middleware {public class PrimeCheckerMiddleware{private readonly RequestDelegate _next;private readonly PrimeCheckerOptions _options;private readonly PrimeService _primeService;public PrimeCheckerMiddleware(RequestDelegate next,PrimeCheckerOptions options,PrimeService primeService){if (next == null){throw new ArgumentNullException(nameof(next));}if (options == null){throw new ArgumentNullException(nameof(options));}if (primeService == null){throw new ArgumentNullException(nameof(primeService));}_next = next;_options = options;_primeService = primeService;}public async Task Invoke(HttpContext context){var request = context.Request;if (!request.Path.HasValue ||request.Path != _options.Path){await _next.Invoke(context);}else{int numberToCheck;if (int.TryParse(request.QueryString.Value.Replace("?", ""), out numberToCheck)){if (_primeService.IsPrime(numberToCheck)){await context.Response.WriteAsync($"{numberToCheck} is prime!");}else{await context.Response.WriteAsync($"{numberToCheck} is NOT prime!");}}else{await context.Response.WriteAsync($"Pass in a number to check in the form {_options.Path}?5");}}}} }由于此中間件在其路徑匹配時充當請求委派鏈中的端點,因此當此中間件處理請求時,不會調(diào)用_next.Invoke。
創(chuàng)建好了這個中間件和一些有用的擴展方法,配置他們更容易,重構(gòu)的配置方法如下所示:
public void Configure(IApplicationBuilder app,IHostingEnvironment env) {if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UsePrimeChecker();app.Run(async (context) =>{await context.Response.WriteAsync("Hello World!");}); }在重構(gòu)之后,可以確信Web應用程序仍然像以前一樣工作,因為您的集成測試全部通過。
Note
在完成重構(gòu)和測試通過后,最好將更改提交給源代碼控制服務。 如果你正在練習測試驅(qū)動開發(fā),考慮添加Commit到你的Red-Green-Refactor循環(huán),詳見這里
Resources
Unit Testing
Middleware
Testing Controllers
轉(zhuǎn)載于:https://www.cnblogs.com/windchen/p/6590723.html
總結(jié)
以上是生活随笔為你收集整理的Integration testing的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: decode encode
- 下一篇: Android学习笔记36:使用SQLi