引言
集成測試可在包含應(yīng)用支持基礎(chǔ)結(jié)構(gòu)(如數(shù)據(jù)庫、文件系統(tǒng)和網(wǎng)絡(luò))的級別上確保應(yīng)用組件功能正常。 ASP.NET Core
通過將單元測試框架與測試 Web
主機和內(nèi)存中測試服務(wù)器結(jié)合使用來支持集成測試。
簡介
集成測試與單元測試相比,能夠在更廣泛的級別上評估應(yīng)用的組件,確認(rèn)多個組件一起工作以生成預(yù)期結(jié)果,包括數(shù)據(jù)庫、文件系統(tǒng)、網(wǎng)絡(luò)設(shè)備等組件。單元測試主要用于測試獨立軟件組件,如類方法,通常使用 fake
或 mock
對象。集成測試使用實際組件,需要更多代碼和數(shù)據(jù)處理,運行時間更長。建議將集成測試限制在重要的基礎(chǔ)結(jié)構(gòu)方案上,若可用單元測試或集成測試測試行為,優(yōu)先選擇單元測試。集成測試中被測試的項目通常稱為"SUT"
,用于指代要測試的應(yīng)用。避免為每種數(shù)據(jù)庫和文件系統(tǒng)交互排列編寫集成測試,而是通過一組集中式讀取、寫入、更新和刪除集成測試充分測試這些組件,使用單元測試測試與這些組件交互的方法邏輯,使用 fake
或 mock
對象可加快測試速度。
集成測試實戰(zhàn)
我們在之前的章節(jié)中創(chuàng)建了Sample.Api
和Sample.Repository
的項目,現(xiàn)在我們對這個項目進(jìn)行整體的集成測試,帶大家來感受一下。
ASP.NET Core
中的集成測試需要以下內(nèi)容:
- 測試項目用于包含和執(zhí)行測試。 測試項目具有對
SUT
的引用。 - 測試項目為
SUT
創(chuàng)建測試Web主機
,并使用測試服務(wù)器客戶端處理SUT
的請求和響應(yīng)。 - 測試運行程序用于執(zhí)行測試并報告測試結(jié)果。
集成測試后跟一系列事件,包括常規(guī)“排列”
、“操作”
和“斷言”
測試步驟:
- 已配置
SUT
的Web
主機。 - 創(chuàng)建測試服務(wù)器客戶端以向應(yīng)用提交請求。
- 執(zhí)行
“排列”
測試步驟:測試應(yīng)用會準(zhǔn)備請求。 - 執(zhí)行
“操作
”`測試步驟:客戶端提交請求并接收響應(yīng)。 - 執(zhí)行
“斷言”
測試步驟:實際響應(yīng)基于預(yù)期響應(yīng)驗證為通過或失敗。 - 該過程會一直繼續(xù),直到執(zhí)行了所有測試。
- 報告測試結(jié)果。
上面解釋到了集成測試中被測試的項目通常稱為SUT
。我們要測試的項目Sample.Api
既是我們的SUT
。
好了我們開始創(chuàng)建xUnit的單元測試項目
,并添加Sample.Api
的項目引用.
集成測試第一步
在我們的單元測試項目中安裝Nuget
依賴
PM> NuGet\Install-Package Microsoft.AspNetCore.Mvc.Testing -Version 8.0.4
基礎(chǔ)結(jié)構(gòu)組件(如測試
Web 主機
和內(nèi)存中測試服務(wù)器 (TestServer
))由Microsoft.AspNetCore.Mvc.Testing
包提供或管理。 使用此包可簡化測試創(chuàng)建和執(zhí)行。
Microsoft.AspNetCore.Mvc.Testing
包處理以下任務(wù):
將依賴項文件 (.deps
) 從 SUT
復(fù)制到測試項目的 bin
目錄中。
將內(nèi)容根目錄設(shè)置為 SUT
的項目根目錄,以便可在執(zhí)行測試時找到靜態(tài)文件和頁面/視圖。
提供 WebApplicationFactory
類,以簡化 SUT
在 TestServer
中的啟動過程。
概念有點多,后續(xù)里面的概念會慢慢講到。
我們知道Asp.Net Core
的Web
項目項目是借助Kestrel
啟動,用集成測試的TestServer
正是代替了Kestrel
托管服務(wù)的啟動,那我們要測試的項目就不需要單獨被啟動了。
什么是TestServer
?
TestServer 用于在集成測試中模擬和啟動應(yīng)用程序的主機環(huán)境。通過創(chuàng)建 TestServer
實例,可以在測試中模擬出一個運行中的應(yīng)用程序?qū)嵗员氵M(jìn)行端到端的集成測試。
在
Microsoft.AspNetCore.Mvc.Testing
中已經(jīng)默認(rèn)集成了對TestServer
的支持所以,不需要額外進(jìn)行配置。
SUT
環(huán)境?
如果未設(shè)置 SUT
的環(huán)境,則環(huán)境會默認(rèn)為開發(fā)環(huán)境即 Development
。
向測試項目公開啟動類Program
使用 WebApplicationFactory<TEntryPoint>
創(chuàng)建 TestServer
以進(jìn)行集成測試。 TEntryPoint
是 SUT
的入口點類,通常是 Program.cs
。
有兩種向測試項目公開 Program
的方法
- 在
Program.cs
添加部分類
var builder = WebApplication.CreateBuilder(args);
// ... Configure services, routes, etc.
app.Run();
+ public partial class Program { }
- 配置
MSBuild
在SUT
的csproj
文件下添加
<ItemGroup>
<Using Include="Sample.Api" />
<InternalsVisibleTo Include="dotNetParadise.IntegrationTest" />
</ItemGroup>
-
<Using Include="Sample.Api" />
:這個子元素指定了要在項目中使用的命名空間或程序集。在這里,Sample.Api
被包含在項目中,以便項目可以訪問和使用該命名空間或程序集中的內(nèi)容。 -
<InternalsVisibleTo Include="dotNetParadise.IntegrationTest" />
:這個子元素用于將內(nèi)部可見性(InternalsVisibleTo
)屬性應(yīng)用于項目,允許指定的程序集(在這里是dotNetParadise.IntegrationTest
)訪問項目中的內(nèi)部成員。這在單元測試或集成測試中非常有用,因為測試項目通常需要訪問被測試項目的內(nèi)部成員以進(jìn)行更全面的測試。
相對來說更推薦使用第一種部分類的形式來對測試項目公開。
WebApplicationFactory
可以使用默認(rèn)的WebApplicationFactory
和自定義的WebApplicationFactory
來進(jìn)行集成測試
測試類實現(xiàn)一個類固定例程接口 (IClassFixture
),以指示類包含測試,并在類中的所有測試間提供共享對象實例。
來感受一下
使用默認(rèn) WebApplicationFactory 的基本測試
看一下如何使用
public class DefaultWebApplicationFactoryTest : IClassFixture<WebApplicationFactory<Program>>
{
private readonly WebApplicationFactory<Program> _factory;
public DefaultWebApplicationFactoryTest(WebApplicationFactory<Program> factory)
{
_factory = factory;
}
[Fact]
public async Task GetAll_Query_ReturnOkAndListStaff()
{
//Arrange
var httpClient = _factory.CreateClient();
//act
var response = await httpClient.GetAsync("/api/Staff");
//Assert
//校驗狀態(tài)碼
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//校驗用戶
var users = await response.Content.ReadFromJsonAsync<List<Staff>>();
Assert.NotNull(users);
}
[Fact]
public async Task GetConfig_WhenCalled_ReturnOk() {
//Arrange
var httpClient = _factory.CreateClient();
//act
var response = await httpClient.GetAsync("/GetConfig");
//Assert
//校驗狀態(tài)碼
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//校驗用戶
var config = await response.Content.ReadFromJsonAsync<string>();
Assert.NotNull(config);
}
}
看到我們的測試類繼承了IClassFixture
來共享實例對象,并且泛型類型是默認(rèn)的WebApplicationFactory<Program>
接下來在我們的SUT
即Sample.Api
的program
中打個斷點來驗證一下
看到了我們測試時默認(rèn)的 WebApplicationFactory
使用默認(rèn)配置啟動應(yīng)用程序主機,包括加載 appsettings.json
等配置文件。
在我們的appsettings.Development.json
中加了一個配置
{
"Config": "這里是appsettings.Development.json"
}
GetConfig_WhenCalled_ReturnOk
測試方法看下結(jié)果
正確的讀到appsettings.Development.json
的內(nèi)容了,從而可以得出我們上面的結(jié)論,如果未設(shè)置 SUT
的環(huán)境,則環(huán)境會默認(rèn)為開發(fā)環(huán)境即 Development
。
從上面我們看到我們向SUT
發(fā)請求是調(diào)用的CreateClient()
:CreateClient()
方法用于創(chuàng)建一個 HttpClient
實例,用于模擬客戶端與 SUT
進(jìn)行交互。通過這個 HttpClient
,測試代碼可以發(fā)送 HTTP
請求到應(yīng)用程序,并驗證應(yīng)用程序的響應(yīng)。
總的來說默認(rèn)的 WebApplicationFactory
提供了一種快速啟動應(yīng)用程序主機進(jìn)行集成測試的方式,適用于簡單的測試場景。
自定義 WebApplicationFactory
通過從 WebApplicationFactory<TEntryPoint>
來創(chuàng)建一個或多個自定義工廠,可以獨立于測試類創(chuàng)建 Web
主機配置
我們來創(chuàng)建一個SampleApiWebAppFactory
的類,然后繼承WebApplicationFactory<Program>
public class SampleApiWebAppFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) =>
{
});
builder.UseEnvironment("Production");
base.ConfigureWebHost(builder);
}
public HttpClient Client()
{
return CreateDefaultClient();
}
}
里面有Asp.Net Core
啟動項配置,我們都可以在自定義的SampleApiWebAppFactory
進(jìn)行重寫, 自定義的 WebApplicationFactory
提供了一種靈活的方式來定制化應(yīng)用程序主機的配置,并擴展功能以滿足特定的測試需求。通過繼承并重寫 ConfigureWebHost
方法等,開發(fā)人員可以對應(yīng)用程序主機進(jìn)行自定義配置,包括添加新的服務(wù)、中間件或修改默認(rèn)配置,從而在測試環(huán)境中模擬特定的場景或功能。
優(yōu)勢和功能擴展:
-
定制化配置: 自定義的
WebApplicationFactory
允許開發(fā)人員根據(jù)測試需求添加自定義配置,比如測試環(huán)境特定的服務(wù)、中間件或其他設(shè)置,以確保測試環(huán)境與實際生產(chǎn)環(huán)境保持一致或滿足特定測試需求。 -
功能擴展: 通過重寫
ConfigureWebHost
方法,開發(fā)人員可以擴展應(yīng)用程序主機的功能,例如注冊額外的服務(wù)、修改中間件管道、添加測試專用的配置等,從而更好地適應(yīng)測試場景。
復(fù)雜性和維護(hù):
-
定制化代碼量增加: 自定義的
WebApplicationFactory
可能會包含更多的定制化代碼,需要更多的理解和維護(hù),但這樣可以更好地控制應(yīng)用程序主機的配置和功能。 -
更高的靈活性: 雖然需要更多的理解和維護(hù),但自定義的
WebApplicationFactory
提供了更大的靈活性和定制性,可以滿足更復(fù)雜的測試需求,并確保測試環(huán)境的準(zhǔn)確性和一致性。
總的來說,通過自定義的 WebApplicationFactory
,開發(fā)人員可以根據(jù)具體的測試場景和需求定制化配置和功能,以確保在集成測試中能夠模擬真實的應(yīng)用程序環(huán)境,并進(jìn)行更全面和準(zhǔn)確的測試。這種方式允許開發(fā)人員更好地控制應(yīng)用程序主機的設(shè)置,以適應(yīng)不同的測試需求和場景。
SUT
的數(shù)據(jù)庫上下文在 Program.cs
中注冊。 測試應(yīng)用的 builder.ConfigureServices
回調(diào)在執(zhí)行應(yīng)用的 Program.cs
代碼之后執(zhí)行。 若要將與應(yīng)用數(shù)據(jù)庫不同的數(shù)據(jù)庫用于測試,必須在 builder.ConfigureServices
中替換應(yīng)用的數(shù)據(jù)庫上下文。
builder.ConfigureServices((context, services) =>
{
var descriptor = new ServiceDescriptor(
typeof(DbContextOptions<SampleDbContext>),
serviceProvider => DbContextFactory<SampleDbContext>(serviceProvider, (sp, o) =>
{
o.UseInMemoryDatabase("TestDB");
}),
ServiceLifetime.Scoped);
services.Replace(descriptor);
});
上面用到的DbContextFactory
方法
private static DbContextOptions<TContext> DbContextFactory<TContext>(IServiceProvider applicationServiceProvider,
Action<IServiceProvider, DbContextOptionsBuilder> optionsAction)
where TContext : DbContext
{
var builder = new DbContextOptionsBuilder<TContext>(
new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>()));
builder.UseApplicationServiceProvider(applicationServiceProvider);
optionsAction?.Invoke(applicationServiceProvider, builder);
return builder.Options;
}
來寫個集成測試
public class SampleApiTest(SampleApiWebAppFactory factory) : IClassFixture<SampleApiWebAppFactory>
{
[Fact]
public async Task GetAll_Query_ReturnOkAndListStaff()
{
//Arrange
var httpClient = factory.CreateClient();
//act
var response = await httpClient.GetAsync("/api/Staff");
//Assert
//校驗狀態(tài)碼
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//校驗用戶
var users = await response.Content.ReadFromJsonAsync<List<Staff>>();
Assert.NotNull(users);
}
[Fact]
public async Task GetConfig_WhenCalled_ReturnOk()
{
//Arrange
var httpClient = factory.CreateClient();
//act
var response = await httpClient.GetAsync("/GetConfig");
//Assert
//校驗狀態(tài)碼
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//校驗用戶
var config = await response.Content.ReadFromJsonAsync<string>();
Assert.NotNull(config);
}
// 后面測試省略。。。。
}
最后
集成測試是確保應(yīng)用組件在包含數(shù)據(jù)庫、文件系統(tǒng)和網(wǎng)絡(luò)等基礎(chǔ)結(jié)構(gòu)的級別上正常運行的重要方式。ASP.NET Core
通過結(jié)合單元測試框架、測試Web
主機和內(nèi)存中測試服務(wù)器來支持集成測試。
在集成測試中,我們評估應(yīng)用組件在更廣泛的級別上的功能,驗證多個組件一起工作以生成預(yù)期結(jié)果,包括數(shù)據(jù)庫、文件系統(tǒng)、網(wǎng)絡(luò)設(shè)備等。單元測試主要用于測試獨立的軟件組件,而集成測試需要使用實際組件,涉及更多的代碼和數(shù)據(jù)處理,以及更長的運行時間。建議將集成測試限制在重要的基礎(chǔ)結(jié)構(gòu)方案上,優(yōu)先選擇單元測試或集成測試來測試行為。
在集成測試中,被測試的項目通常稱為SUT
(System Under Test
),用于指代要測試的應(yīng)用。避免為每種數(shù)據(jù)庫和文件系統(tǒng)交互編寫?yīng)毩⒌募蓽y試,而是通過一組集中式的測試來全面測試這些組件,并使用單元測試來測試與這些組件交互的方法邏輯。
通過自定義的WebApplicationFactory
,可以根據(jù)測試需求定制化配置和功能,模擬真實的應(yīng)用程序環(huán)境進(jìn)行全面和準(zhǔn)確的測試。自定義的WebApplicationFactory
提供了靈活性和定制性,滿足復(fù)雜的測試需求,并確保測試環(huán)境的準(zhǔn)確性。雖然自定義的WebApplicationFactory
可能需要更多的理解和維護(hù),但能更好地適應(yīng)不同的測試場景。文章來源:http://www.zghlxwxcb.cn/news/detail-855015.html
集成測試是確保應(yīng)用程序正常運行的關(guān)鍵步驟,通過綜合不同組件的功能來驗證應(yīng)用的整體表現(xiàn),提高應(yīng)用程序的質(zhì)量和穩(wěn)定性。文章來源地址http://www.zghlxwxcb.cn/news/detail-855015.html
- ASP.NET Core 中的集成測試
- 本文完整源代碼
到了這里,關(guān)于實戰(zhàn)指南:使用 xUnit 和 ASP.NET Core 進(jìn)行集成測試【完整教程】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!