簡體   English   中英

在單元測試中獲取配置

[英]Get configuration in Unit Test

我不知道如何通過遵循 IOptions 模式來獲得我正在使用的一些配置。

我要測試的服務是下一個:

        private readonly Dictionary<ErrorType, ErrorObject> _errors;

        public UserService(
            ...(Many services)...
            IOptions<Dictionary<ErrorType, ErrorObject>> errors)
        {
            ...
            _errors = errors.Value;
        }

其中 ErrorType 是一個 Enum 和 ErrorObject,一個 object,其格式與我的 appsettings.json 中的錯誤格式相同。 就是這個:

{
  "Errors": {
    "UserNotFound": {
      "ErrorCode": 101,
      "Message": "User not found"
    },
    "WrongPassword": {
      "ErrorCode": 102,
      "Message": "Wrong password"
    }
  }
}

所以這工作得很好,但我現在的問題是我不知道如何實例化它,模擬它,或者在我的測試 class 中注入它,因為即使我在注入它我也無法在這樣的 class 中解決它總是得到一個 null。 我在測試夾具中像這樣注入它(與我真正的注入模塊中相同):

serviceCollection.Configure<Dictionary<BusinessErrorType, BusinessErrorObject>>(x => Configuration.GetSection("Errors").Bind(x));

我必須正確地注入帶有所有錯誤的 IConfiguration,但我無法為構造函數創建所需的 Dictionary。

在這里,我得到了沒有任何問題的錯誤:

IConfiguration Configuration = ioCModule.ServiceProvider.GetRequiredService<IConfiguration>();
            var errorsConfig = Configuration.GetSection("Errors");

現在我要弄清楚在這個聲明中要寫什么:

var _options = Options.Create<Dictionary<BusinessErrorType, BusinessErrorObject>>();

我在測試夾具中像這樣注入它(與我真正的注入模塊中相同):

您已經嘗試注入字典,而您的 class 期望獲得選項。 嘗試注冊和注入選項,很可能它會成功。

現在我要弄清楚在這個聲明中要寫什么:

Options object 只是一些准備使用價值的持有人,或者什么都沒有。 您必須構造Options object ,要么給它值,要么什么都不給它(並以空選項對象結束)。 如果您使用不帶任何參數的Options.Create<Dict>() ,您將創建一個空的 object,僅此而已。 只需在此之前創建字典並將其傳遞給 Options 工廠。

var dict = new Dictionary<BusinessErrorType, BusinessErrorObject>();
dict.Add("UserNotFound", new BusinessErrorObject(....));
dict.Add("WrongPassword", new BusinessErrorObject(....));

var _options = Options.Create<Dictionary<BusinessErrorType, BusinessErrorObject>>(dict);
// now you have it: _options with some data inside

如果您指望將 Bind() 與 Options 一起使用 - 我懷疑它會不會像那樣工作,因為 Bind 用於使用從設置文件讀取的配置來填充數據結構,而 Options 只是 shell,類似於“Nullable< >”,它的存在只是為了傳遞東西......但是我想你可以先創建一個字典,然后用配置填充它(即綁定),然后用選項<>包裝剛剛填充的字典,然后注冊它IoC 中的選項 object,因此您的 UserService 可以獲取其配置。但是,我不能 100% 確定 Bind 是否足夠智能以填充通用字典。 你需要自己測試它,不幸的是我手頭沒有任何 aspnetcore 項目可以玩

編輯/旁注:

我有點驚訝您在UNIT TEST中構建/設置整個 IoC。 創建單元測試時,您希望盡可能多地剪切/模擬依賴項。 這意味着,沒有 IoC,它可以在測試中引入另一組問題/失敗/等。

我的意思是,我希望您的單元測試看起來像:

[Test]
public void FoobarizingTheBaz()
{
    var mock1 = ....;
    var mock2 = ....;
    var mock3 = ....;
    var ... = ....;
    var mockN = ....;

    var dict = new Dictionary<....>();
    dict.Add(....);
    dict.Add(....);
    var mockOptions = Options.Create<...>(dict);

    var tested = new UserService(
        mock1, mock2, mock3, ... mockN, mockOptions
    );

    var result = tested.FoobarizeTheBaz();

    // assert...
}

那是一個單元測試。 只有經過測試的 object 被實例化,rest 被模擬,你只提供絕對必要的東西。 當然,我不得不編寫大量的設置/模擬/等,而不是依靠 IoC 來自動實現它們,但是一旦模擬被編寫出來,你可以把它們拿出來一些通用代碼,測試 class 初始化、夾具等並重復使用它們。

我的意思是,沒有 appsettings.json。 沒有 IConfiguration。 沒有 IoC 等。

如果您想測試有多少組件相互交互,那么它更像是集成測試。 在這種情況下,您可能希望看到這篇文章涉及在集成測試設置中使用自定義 appsettings.json 和 IOptions。 但是,請注意,aspnetcore 中的“集成測試”通常意味着測試您的服務如何響應請求並檢查響應,因此您將在本文中看到這一點。 不過,關於 IOptions 的部分應該會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM