I want to create a custom appsettings.json file for Unit testing in a MSTest project. I'm calling it testsettings.json. I'm using the repository pattern in the main project, so I have an IUnitOfWork and UnitOfWork that I declare as a Singleton in the ASP.NET side. This gives access to various repositories.
This UnitOfWork does rely on a few config variables, so I use appsettings.json to store these. So, the constructor for the UnitOfWork accepts an IConfigurationvariable that gets parsed via dependency injection and all those smart things in ASP.NET.
However, in the MSTest project there's no such. So, I need to create the IConfiguration object myself to use the constructor. I looked at the code from these StackOverflow links:
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
However, the problem is that in NET Core 3.1 I can't use this:
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath([PATH_WHERE_appsettings.json_RESIDES])
.AddJsonFile("appsettings.json")
.Build();
So, I've resorted to reading in the JSON file as a string, converting it to a Dict<string, string>
using Newtonsoft.Json and then parsing it to the config file. It's not optimized, and I have to use a different appsettings.json structure because I cannot parse JSON objects to the string dictionary.
So I have to do this:
{
"var1": "abc",
"var2": "def",
"var3": "hij"
}
Instead of this:
{
"obj1": {
"var1": "abc",
"var2": "def",
"var3": "hij"
}
}
Here's my implementation:
//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 - Solve the Json object parsing problem above
To solve the problem of adding Json objects into my testsettings.json I used the following:
//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();
Does anyone know how to do this in a better way?