【问题标题】:appsettings.json for MSTest [ASP.NET Core 3.1]用于 MSTest [ASP.NET Core 3.1] 的 appsettings.json
【发布时间】:2020-08-27 09:01:25
【问题描述】:

我想为 MSTest 项目中的单元测试创​​建自定义 appsettings.json 文件。我称它为 testsettings.json。我在主项目中使用存储库模式,所以我有一个 IUnitOfWork 和 UnitOfWork,我在 ASP.NET 端声明为 Singleton。这可以访问各种存储库。

这个 UnitOfWork 确实依赖于一些配置变量,所以我使用 appsettings.json 来存储这些。因此,UnitOfWork 的构造函数接受一个 IConfiguration 变量,该变量通过依赖注入和 ASP.NET 中的所有智能事物进行解析。

但是,在 MSTest 项目中没有这样的。因此,我需要自己创建 IConfiguration 对象才能使用构造函数。我查看了这些 StackOverflow 链接中的代码:

How can I create an instance of IConfiguration locally?

Populate IConfiguration for unit tests

How can I add a custom JSON file into IConfiguration?

Using IConfiguration in C# Class Library

但是,问题是在 NET Core 3.1 中我不能使用这个:

IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath([PATH_WHERE_appsettings.json_RESIDES])
            .AddJsonFile("appsettings.json")
            .Build();

因此,我求助于将 JSON 文件作为字符串读取,使用 Newtonsoft.Json 将其转换为 Dict<string, string>,然后将其解析为配置文件。它没有经过优化,我必须使用不同的 appsettings.json 结构,因为我无法将 JSON 对象解析为字符串字典。

所以我必须这样做:

{
  "var1": "abc",
  "var2": "def",
  "var3": "hij"
}

而不是这个:

{
  "obj1": {
    "var1": "abc",
    "var2": "def",
    "var3":  "hij"    
  }
}

这是我的实现:

//setup logger
//-------------------
var loggerFactory = LoggerFactory.Create(builder =>
    {
    builder
       .AddFilter("Microsoft", LogLevel.Warning)
       .AddFilter("System", LogLevel.Warning)
       .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug);
    });
    testLogger = loggerFactory.CreateLogger<LocationRecordManagerTests>();
    testLogger.LogInformation("Init FileName of unit tests");

//setup config file
//-------------------
//get file path
string liveFolder = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
string projectFolder = Directory.GetParent(liveFolder).FullName;
string filePath = Path.Combine(projectFolder, "testsettings.json");
//get json as string data
string jsonString = File.ReadAllText(filePath);
Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
//build config file
var configBuilder = new ConfigurationBuilder();
configBuilder.AddInMemoryCollection(jsonDict);
var configFile = configBuilder.Build();
//test - this works
//object value = configFile.GetSection("var1");

//create UnitOfWork
//-------------------
testUnitOfWork = new UnitOfWork(testLogger, configFile);

Edit - 解决上面的Json对象解析问题

为了解决将 Json 对象添加到我的 testsettings.json 中的问题,我使用了以下内容:

//setup config file
//-------------------
//get file path
string liveFolder = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
string projectFolder = Directory.GetParent(liveFolder).FullName;
string filePath = Path.Combine(projectFolder, "testsettings.json");
//get json as string data
string jsonString = File.ReadAllText(filePath);
Dictionary<string, string> jsonDict, jsonObjectValues;

try
{

    Dictionary<string, object> objectDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);

    //get objectData
    object objectData = objectDict.GetValueOrDefault("RecordCollections");
    var jsonObjectData = JsonConvert.SerializeObject(recordData);
    jsonObjectValues = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonRecordData);

    //then use objectDict.Remove(..) to remove duplications

    jsonDict = objectDict.ToDictionary(x => x.Key, x => x.Value.ToString());
}
catch (Exception e)
{
    throw e;
}

//build config file
var configBuilder = new ConfigurationBuilder();
//add variables from json file
configBuilder.AddInMemoryCollection(jsonDict);
// add object variables from json file
configBuilder.AddInMemoryCollection(jsonObjectValues);
var configFile = configBuilder.Build();

有谁知道如何以更好的方式做到这一点?

【问题讨论】:

  • 为什么不能像你说的那样引用它?这绝对是可能的,所以我认为你需要解释为什么它不适合你
  • 为什么不使用MemoryConfigurationSource
  • @pinkfloydx33,所以当我在 JSON 中的对象中有项目时(如 obj1 所示),我会收到 JsonConvert 错误。它说“解析值时遇到意外字符:{. Path 'obj1', line 2, ....”我不能使用字符串,对象字典,因为 configBuilder 只接受字符串,字符串类型。
  • @PavelAnikhouski 我真的不明白这会有什么好处。我是否仍然不必将我的 testsettings.json 解析为 IConfigurationBuilder,然后将其与 MemoryConfigurationSource 一起使用?
  • @itstudes 可以在MemoryConfigurationSource中填写InitialData字典,无需解析json文件

标签: c# json asp.net-core mstest appsettings


【解决方案1】:

请参阅此Configuration in ASP.NET Core 示例 bind-hierarchical-configuration-data-using-the-options-pattern。无论将配置放在appsettings.json 还是testsettings.json 中,您都可以将它们绑定到您的模型中,命名为UnitOfWorkModel,例如下面的示例。

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  },
  "UnitOfWork": {
    "var1": "abc",
    "var2": "def",
    "var3": "hij"
  }
}

testsettings.json

{
  "var1": "abc",
  "var2": "def",
  "var3": "hij"
}

你可以先声明一个绑定模型进行配置

public class UnitOfWorkModel
{
    public string Var1 { get; set; }
    public string Var2 { get; set; }
    public string Var3 { get; set; }
}

然后,在 .NET Core 启动时从原生 IConfiguration 对象绑定到 UnitOfWorkModel

public Startup(IConfiguration configuration)
{
    IConfigurationSection section = configuration.GetSection("UnitOfWork");
    IConfiguration configuration = section as IConfiguration;

    IEnumerable<IConfigurationSection> items = configuration.GetSection("UnitOfWork").GetChildren();
    // items.Count() == 3

    Dictionary<string, string> dict = items.ToDictionary(o => o.Key, o => o.Value);
    // dict.Count() == 3

    var unitOfWorkModel = new UnitOfWorkModel();
    section.Bind(unitOfWorkModel);
    // unitOfWorkModel.Var1 == "abc";
    // unitOfWorkModel.Var2 == "def";
    // unitOfWorkModel.Var3 == "hij";
}

或者,通过 unittest 测试绑定结果(这里是带有依赖关系的 .NET Core 的 xUnit 测试框架示例,Microsoft.Extensions.Configuration.Json NuGet 包)

[xUnit]
public void BindTest()
{
    IConfigurationRoot root = new ConfigurationBuilder()
        .AddJsonFile("testsettings.json")
        .Build();

    IConfiguration configuration = root as IConfiguration;
    Assert.NotNull(configuration);

    var unitOfWorkModel = new UnitOfWorkModel();
    root.Bind(unitOfWorkModel);

    Assert.Equals("abc", unitOfWorkModel.Var1);
    Assert.Equals("def", unitOfWorkModel.Var2);
    Assert.Equals("hij", unitOfWorkModel.Var3);
}

任何一种方式都应该适用于超级界面IConfiguration

【讨论】:

  • 据我所知,.AddJsonFile(..) 功能在 Net Core 3.1 中不可用,因此您无法按照 xUnit 测试框架的说明构建文件。
  • @itstudes 或许你可以nuget Microsoft.Extensions.Configuration.Json 包,然后大概可以在Microsoft.Extensions.Configuration 的命名空间中看到.AddJsonFile 扩展方法
猜你喜欢
  • 1970-01-01
  • 2017-05-13
  • 2020-06-16
  • 1970-01-01
  • 2020-06-11
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 2017-11-01
相关资源
最近更新 更多