| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- namespace Apq.Cfg.Tests;
- /// <summary>
- /// JSON 配置源测试
- /// </summary>
- public class JsonCfgTests : IDisposable
- {
- private readonly string _testDir;
- public JsonCfgTests()
- {
- _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgTests_{Guid.NewGuid():N}");
- Directory.CreateDirectory(_testDir);
- }
- public void Dispose()
- {
- if (Directory.Exists(_testDir))
- {
- Directory.Delete(_testDir, true);
- }
- }
- [Fact]
- public void Get_SimpleValue_ReturnsCorrectValue()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """
- {
- "AppName": "TestApp",
- "Version": "1.0.0"
- }
- """);
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal("TestApp", cfg["AppName"]);
- Assert.Equal("1.0.0", cfg["Version"]);
- }
- [Fact]
- public void Get_NestedValue_ReturnsCorrectValue()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """
- {
- "Database": {
- "Host": "localhost",
- "Port": 5432
- }
- }
- """);
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal("localhost", cfg["Database:Host"]);
- Assert.Equal("5432", cfg["Database:Port"]);
- }
- [Fact]
- public void Get_TypedValue_ReturnsCorrectType()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """
- {
- "Settings": {
- "MaxRetries": 3,
- "Enabled": true,
- "Timeout": 30.5
- }
- }
- """);
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(3, cfg.GetValue<int>("Settings:MaxRetries"));
- Assert.True(cfg.GetValue<bool>("Settings:Enabled"));
- Assert.Equal(30.5, cfg.GetValue<double>("Settings:Timeout"));
- }
- [Fact]
- public void Exists_ExistingKey_ReturnsTrue()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"Key": "Value"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.True(cfg.Exists("Key"));
- Assert.False(cfg.Exists("NonExistent"));
- }
- [Fact]
- public async Task Set_AndSave_PersistsValue()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"Original": "Value"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
- .Build();
- // Act
- cfg.SetValue("NewKey", "NewValue");
- await cfg.SaveAsync();
- // Assert - 重新读取验证
- using var cfg2 = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- Assert.Equal("NewValue", cfg2["NewKey"]);
- Assert.Equal("Value", cfg2["Original"]);
- }
- [Fact]
- public async Task Remove_AndSave_RemovesKey()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"ToRemove": "Value", "ToKeep": "Value2"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
- .Build();
- // Act
- cfg.Remove("ToRemove");
- await cfg.SaveAsync();
- // Assert
- using var cfg2 = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // 验证删除后值为 null 或空字符串
- var removedValue = cfg2["ToRemove"];
- Assert.True(string.IsNullOrEmpty(removedValue), $"Expected null or empty, but got: '{removedValue}'");
- Assert.Equal("Value2", cfg2["ToKeep"]);
- }
- [Fact]
- public void MultiLevel_HigherLevelOverrides()
- {
- // Arrange
- var basePath = Path.Combine(_testDir, "base.json");
- var overridePath = Path.Combine(_testDir, "override.json");
- File.WriteAllText(basePath, """
- {
- "Setting1": "BaseValue1",
- "Setting2": "BaseValue2"
- }
- """);
- File.WriteAllText(overridePath, """
- {
- "Setting1": "OverrideValue1"
- }
- """);
- using var cfg = new CfgBuilder()
- .AddJson(basePath, level: 0, writeable: false)
- .AddJson(overridePath, level: 1, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal("OverrideValue1", cfg["Setting1"]); // 被覆盖
- Assert.Equal("BaseValue2", cfg["Setting2"]); // 保持原值
- }
- [Fact]
- public void ToMicrosoftConfiguration_ReturnsValidConfiguration()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """
- {
- "App": {
- "Name": "TestApp"
- }
- }
- """);
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act
- var msConfig = cfg.ToMicrosoftConfiguration();
- // Assert
- Assert.NotNull(msConfig);
- Assert.Equal("TestApp", msConfig["App:Name"]);
- }
- [Fact]
- public void Get_LongValue_ReturnsCorrectType()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"BigNumber": 9223372036854775807}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(9223372036854775807L, cfg.GetValue<long>("BigNumber"));
- }
- [Fact]
- public void Get_DecimalValue_ReturnsCorrectType()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"Price": 123.456}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(123.456m, cfg.GetValue<decimal>("Price"));
- }
- public enum TestLogLevel { Debug, Info, Warning, Error }
- [Fact]
- public void Get_EnumValue_ReturnsCorrectType()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"LogLevel": "Warning"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(TestLogLevel.Warning, cfg.GetValue<TestLogLevel>("LogLevel"));
- }
- [Fact]
- public void Get_EnumValue_CaseInsensitive()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"LogLevel": "warning"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(TestLogLevel.Warning, cfg.GetValue<TestLogLevel>("LogLevel"));
- }
- [Fact]
- public void Get_InvalidValue_ReturnsDefault()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"NotANumber": "abc"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert - 无效值返回默认值(与 Microsoft.Extensions.Configuration 行为一致)
- Assert.Equal(default(int), cfg.GetValue<int>("NotANumber"));
- }
- [Fact]
- public void Get_NonExistentKey_ReturnsDefault()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"Key": "Value"}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Null(cfg["NonExistent"]);
- Assert.Equal(default, cfg.GetValue<int>("NonExistent"));
- Assert.Null(cfg.GetValue<string>("NonExistent"));
- }
- [Fact]
- public void Get_NullableInt_ReturnsCorrectValue()
- {
- // Arrange
- var jsonPath = Path.Combine(_testDir, "config.json");
- File.WriteAllText(jsonPath, """{"NullableInt": 42}""");
- using var cfg = new CfgBuilder()
- .AddJson(jsonPath, level: 0, writeable: false)
- .Build();
- // Act & Assert
- Assert.Equal(42, cfg.GetValue<int?>("NullableInt"));
- Assert.Null(cfg.GetValue<int?>("NonExistent"));
- }
- }
|