筆者平時在開發時通常都會加上單元測試,因為現在寫測試很容易,與其每次修改都要再次手動測試,還不如寫一次自動測試。只是通常單元測試覆蓋率都不會高到哪裡去,只有比較重要的地方會寫單元測試,一方面是時間不夠,另一方面是不容易測試。例如檔案讀取
或許有些人會覺得檔案讀取還需要測試?! 不過這個套件在 NuGet 上有超過 4200 萬的下載,代表這個測試也不是完全不重要。
註: 此套件還有一個名稱是 TestableIO.System.IO.Abstractions ,他多了 TestableIO 前綴,用來用於辨識是非官方。官方說明兩個是相同的,不過在筆者的測試下發現 TestableIO.System.IO.Abstractions 一定要再裝他的 TestingHelpers 才能夠正常使用,不然會找不到 FileSystem 。
再使用 NuGet 安裝 System.IO.Abstractions.TestingHelpers 套件,或是使用 .NET CLI 執行以下指令安裝
System.IO.Abstractions 套件是新增檔案相關的介面,而 System.IO.Abstractions.TestingHelpers 套件則是用於模擬檔案相關操作
一般程式碼直接使用系統的 FileSystem (已經寫在無參數的建構子,不須額外傳入)
測試時使用 MockFileSystem 建立模擬的檔案,裡面傳入測試內容,讀取時不會去讀取到實際檔案,而是自訂的內容。
若沒有先在 MockFileSystem 中放入檔案路徑,就會視為沒有此檔案,模擬找不到檔案時的情境,拋出的例外如下:
參考資料:
Github - TestableIO/System.IO.Abstractions
或許有些人會覺得檔案讀取還需要測試?! 不過這個套件在 NuGet 上有超過 4200 萬的下載,代表這個測試也不是完全不重要。
安裝
先使用 NuGet 安裝 System.IO.Abstractions 套件,或是使用 .NET CLI 執行以下指令安裝:
dotnet add package System.IO.Abstractions
註: 此套件還有一個名稱是 TestableIO.System.IO.Abstractions ,他多了 TestableIO 前綴,用來用於辨識是非官方。官方說明兩個是相同的,不過在筆者的測試下發現 TestableIO.System.IO.Abstractions 一定要再裝他的 TestingHelpers 才能夠正常使用,不然會找不到 FileSystem 。
再使用 NuGet 安裝 System.IO.Abstractions.TestingHelpers 套件,或是使用 .NET CLI 執行以下指令安裝
dotnet add package System.IO.Abstractions.TestingHelpers
System.IO.Abstractions 套件是新增檔案相關的介面,而 System.IO.Abstractions.TestingHelpers 套件則是用於模擬檔案相關操作
範例程式碼
沒有參數的建構子使用系統的 FileSystem ,然後多加了一個有參數的建構子,方便測試時使用。
using System.IO.Abstractions;
public class MyService
{
private readonly IFileSystem _fileSystem;
public MyService()
{
_fileSystem = new FileSystem();
}
public MyService(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public string ReadFile(string path)
{
return _fileSystem.File.ReadAllText(path);
}
}
一般程式碼直接使用系統的 FileSystem (已經寫在無參數的建構子,不須額外傳入)
MyService myService = new MyService();
string file = myService.ReadFile(@"C:\Users\ruyut\Desktop\my.json");
Console.WriteLine(file);
測試時使用 MockFileSystem 建立模擬的檔案,裡面傳入測試內容,讀取時不會去讀取到實際檔案,而是自訂的內容。
var mockFileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"C:\Users\ruyut\Desktop\my.json", new MockFileData("這是檔案的內容") },
}
);
MyService myService = new MyService(mockFileSystem);
string file = myService.ReadFile(@"C:\Users\ruyut\Desktop\my.json");
Console.WriteLine(file);
若沒有先在 MockFileSystem 中放入檔案路徑,就會視為沒有此檔案,模擬找不到檔案時的情境,拋出的例外如下:
17360 C:/Users/ruyut/Documents/RiderProjects/2023/test/ConsoleAppSystem.IO.Abstractions/ConsoleAppSystem.IO.Abstractions/bin/Debug/net6.0/ConsoleAppSystem.IO.Abstractions.exe
Unhandled exception. System.IO.FileNotFoundException: Could not find file 'C:\Users\ruyut\Desktop\my.json'.
File name: 'C:\Users\ruyut\Desktop\my.json'
at System.IO.Abstractions.TestingHelpers.MockFile.ReadAllText(String path, Encoding encoding)
at System.IO.Abstractions.TestingHelpers.MockFile.ReadAllText(String path)
at ConsoleAppSystem.IO.Abstractions.MyService.ReadFile(String path) in C:\Users\ruyut\Documents\RiderProjects\2023\test\ConsoleAppSystem.IO.Abstractions\ConsoleAppSystem.IO.Abstractions\MyService.cs:line 21
at Program.<Main>$(String[] args) in C:\Users\ruyut\Documents\RiderProjects\2023\test\ConsoleAppSystem.IO.Abstractions\ConsoleAppSystem.IO.Abstractions\Program.cs:line 13
Process finished with exit code -532,462,766.
參考資料:
Github - TestableIO/System.IO.Abstractions
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com