前言
前面已經有寫了幾篇關於解耦合,抽象行為等等概念的說明了.
而建置測試專案雖然已經做了第二次了,但發現兩次我都會忘記怎麼做,因此才特別寫了這篇初始化的文章出來
碰到問題
在.NET Core 開發的過程中,都知道有IServiceProvider和IConfiguration這兩個介面可以取得實例或是Config的配置
但正常情況下都被框架包好了,根本不用去考慮他怎麼做出來的.
但在測試的途中,框架不會知道你是否要使用,因此也不會自動幫你建立一個出來,導致我們需要自己來建立.
建立專案
由於我現在的開發環境是 Mac OS 因此這裡就只示範 VSCode & .NET CLI
dotnet new nunit -n {ProjectName}
如果是6版本以上的話,會自動建立using.cs
這個是GloableUsing的部分,如果有全域要使用的using的話可以考慮放到這裡
Nunit的介紹
正常來講在寫整合測試的時候,我們為了減少變因,因此都會做一次初始化以及完畢的行為
例如:初始化建立相依的物件(DB,Redis等等相關連線)
完畢的時候要刪除測試的資料等等行為
而在NUnit中的屬性則叫做Setup(初始) & TearDown(結束)
實際上寫出來會長得像這樣
[SetUp]
public void SetUp()
{
//初始化區塊
}
[TearDown]
public void TearDown()
{
//測試完成後執行的區塊
}
建立IServiceProvider & IConfiguration
建立方式其實沒有很困難,實際方式如下
protected IServiceCollection _services;
protected IServiceProvider _sp;
protected IConfiguration _configuration;
[SetUp]
public void SetUp()
{
// 先建立新的ServiceCollection
this._services = new ServiceCollection();
// 使用檔案進行Config抓取
var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.Test.json");
this._configuration = configuration.Build();
//add MongoDB
var appSettingsSection_MongoDB = _configuration.GetSection("MongoDbConfig");
var appSettingsMongoDB = appSettingsSection_MongoDB.Get<DbConfig>();
this._services.AddScoped<IMongoStorage>(sp => { return new MongoStorage(appSettingsMongoDB); });
this._services.AddSingleton<IMongoFileStorage>(sp => { return new MongoFileStorage(appSettingsMongoDB); });
// 創建出ServiceProvider
this._sp = _services.BuildServiceProvider();
}
[TearDown]
public void TearDown()
{
IMongoStorage db = this._sp.GetRequiredService<IMongoStorage>();
Assert.AreEqual("TestDB",db.GetDB().DatabaseNamespace.DatabaseName, "DB Name must be TestDB");
BsonDocument empty = new BsonDocument();
DeleteResult deleteResult;
deleteResult = db.GetCollection<UserInfo>("UserInfo").DeleteMany(empty);
}
}
當中比較需要特別注意的是 appsettings.Test.json 會需要在csproj裡面特別說明要輸出到輸出目錄,否則會抓不到Config導致報錯
<ItemGroup>
<None Update="appsettings.Test.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
而因為這些比較算是每個測試都會使用的Init 所以其實可以抽成一個BasicTestClass 後續有相關測試的Class可以直接繼承使用,就不用每個Class都寫一次了.
總結
測試其實不難,真正難的會是在開發過程中的設計,如何設計商業邏輯以及低耦合才是最困難的點.