I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks
Related
I initialized the interactive element with the project from the context menu of my project.
I am testing a function in C# interactive that needs to read my app.config file to get a connectionstring.
I got the next error:
No connection string named 'ccnName' could be found in the application config file.
When I use the next code, i get a null value. I suppose it is because it is not reading the app.config of my project.
ConfigurationManager.ConnectionStrings["cnnName"]
It is the only connectionstring that the default app.config has:
[data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true]
In this post from 2012 with the same topic, one engineer involved in this project said that this option was not available. I hope it is available now in 2018
So, nowadays how can i load the app.config that i want?
"Constructor" was the magic word. This may not help in your case since you've found a solution, but it might be helpful for others in the same situation.
If you inject a System.Configuration.Configuration object into the class, you don't have to rely on ConfigurationManager's static properties.
public class LibraryClass
{
private Configuration _configuration;
public LibraryClass(Configuration configuration)
{
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
public void FunctionUnderTest()
{
string connectionString = _configuration.ConnectionStrings.ConnectionStrings["cnnName"].ConnectionString;
// Connect to the database as you normally would.
}
}
In a console/GUI application and unit tests, load it like this to use {anything}.config:
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Register 'configuration' as a singleton using the container of your choice.
In a web application, load it like this to use web.config:
Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/Web.config");
// Register 'configuration' as a singleton using the container of your choice.
To use it in C# Interactive, load it using the first method and provide the dependency to the class directly:
#r "System.Configuration"
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(
new ExeconfigurationFileMap() { ExeConfigFilename = #"path\to\Arbitrary.config" },
ConfigurationUserLevel.None);
var lib = new LibraryClass(configuration);
lib.FunctionUnderTest();
Note that the section properties are an extra layer deep compared to what you would normally expect.
I think it has something to do with how ConfigurationManager's static properties work with the Configuration instance.
I am using an app.config file to store the dynamic parameters of my application. The problem is, when I change a value in app.config file, and start the application, it doesn't load the new value from config file. Seems like the values in app.config file are being read and embedded in exe file only at compile time!
This is how I read the config file:
public class Helper
{
static Helper()
{
Foo = ConfigurationManager.AppSettings["Foo"];
}
public static string Foo { get; set; }
}
Am I missing something?
Are you sure you are changing the correct file? You don't want to change the app.config file, but the <exename>.exe.config file, in the same directory as the .exe
The app.config file is what you edit in the ide, but when you compile your app this file is renamed to <exename>.exe.config and copied to the output directory when you compile. The .exe looks for a file with the same name as itself with the .config extension when looking for the default configuration.
The static nature of your class and method may be causing you the issue. Maybe refactor it to the following...
public static class Helper
{
public static string Foo
{
get
{
return ConfigurationManager.AppSettings["Foo"];
}
}
}
Actually, thinking about it, it doesn't help you a great deal since ConfigurationManager.AppSettings["Foo"] is already (effectively) a static call - you're just adding another layer of abstraction that may well not be required.
I want to initialize a user configuration through a user configuration file. The path for the file can be read from the registry.
The file is located in a folder with the user's name.
So I need the following functionality:
Reading a string from registry
building the path to the configuration file
Reading the file into a configuration object
Now there are several approaches to handle this:
First, I need
one "helper"-class for getting the file path (let's call it Shared)
one "container"-class for the configuration information (let's call it Configuration)
So, Shared has a function/property like UserConfigurationFile which returns the path to the configuration file.
To get the path to the file I have a function InitializeUserConfigurationFile() which is called in the constructor of Shared:
class Shared {
public Shared()
{
InitializeUserConfigurationFile();
}
void InitializeUserConfigurationFile()
{
//
// Reads username
//
//
// Reads path from Registry
//
//
// etc.
//
}
//
// etc.
//
}
Any better suggestions?
When I want to Initialize my Container I have different options:
Is it best to initialize the user configuration within the constructor?
Sth. like:
class Container
{
Shared shared = new Shared();
public Container()
{
InitializeUserConfiguration();
}
void InitializeUserConfiguration()
{
LoadConfiguration(shared.UserConfigurationFile);
}
void LoadConfiguration(string filename)
{
//
// Initializes all parameters frome filename
//
}
}
Or through two steps (through an own method LoadConfiguration())?
Sth. like:
Shared shared = new Shared();
Container container = new Container();
container.LoadConfiguration(shared.UserConfigurationFile);
Or inside the constructor of Container by delivering a filename?
Sth. like:
Shared shared = new Shared();
Container container = new Container(shared.UserConfigurationFile);
or everything in Container..?
There are so many ways...
I hope somebody knows a best-approch...
Regards,
Inno
It is better to use standard configuration classes exist in .net. Such as ApplicationSettingsBase and Configuration.
Here you can find good article series:
Unraveling the Mysteries of .NET 2.0 Configuration
Unraveling the Mysteries of .NET 2.0 Configuration
Cracking the Mysteries of .NET 2.0 Configuration
For best practices, don't use the registry, and don't reinvent the wheel.
Since you didn't mention it, have you looked at the System.Configuration namespace?
The .NET Framework constains a perfectly good configuration system that is well tested. It is also the domain of Sys Admins, who also know about config files and the accompanying tools.
So it is unclear why you are reinventing the wheel, possibly making it a little less round.
There are practical reasons to shun the Registry (distribution, backup) but also, as arbiter points out, it is not going to move to other (future) platforms. Did you notice that those namespaces are not starting with System ?
This is very frustrating... I can set the Configuration File for a Windows Forms Application just fine. Consider this:
public static void Main(){
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", #"SharedAppConfig.config");
//do other things
}
However, in a WPF application, this doesn't seem to work! If I set this value, the value of the AppDomain.CurrentDomain.SetupInformation.ConfigurationFile property is correct, but any calls to that configuration file while debugging yield no results. There are WCF configuration settings in an App.config that I need to share between application, so this is my proposed solution. Is it possible to dynamically set the location of my config file in WPF?
Help! Thanks!
You should be able to do something along the lines of:
using System.Configuration;
public class TryThis
{
Configuration config = ConfigurationManager.OpenExeConfiguration("C:\PathTo\app.exe");
public static void Main()
{
// Get something from the config to test.
string test = config.AppSettings.Settings["TestSetting"].Value;
// Set a value in the config file.
config.AppSettings.Settings["TestSetting"].Value = test;
// Save the changes to disk.
config.Save(ConfigurationSaveMode.Modified);
}
}
NOTE: This will attempt to open a file named app.exe.config at C:\PathTo. This also REQUIRES that a file exists at the same path with the name "app.exe". The "app.exe" file can just be an empty file though. For your case I'd almost make a shared "Config.dll" library that would handle the config file.
~md5sum~
Is this on the service side or the client side? If on the service side, it is often the case that the service is running in its own AppDomain, so that if you set AppDomain.CurrentDomain.SetData(...) it won't apply to the service configuration.
I'm not entirely sure how to get around this, but you should be able to control the service's configuration by implementing your own ServiceHost.
I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks