【发布时间】: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