I searched a lot and still couldn't find a solid solution for this. Suppose you have methods in your application. This methods use "System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration" to access some setting in the web.config. If you try to test these methods, your tests will fail because your test project doesn't have web.config.
What is the best way to solve this problem. For projects with simple config file, I usually use a method like this as facade method.
public class Config
{
public static String getKeyValue(String keyName)
{
if (keyName == String.Empty) return String.Empty;
String result = "";
System.Configuration.Configuration rootWebConfig1 =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(null);
if (rootWebConfig1.AppSettings.Settings.Count > 0)
{
System.Configuration.KeyValueConfigurationElement reportEngineKey =
rootWebConfig1.AppSettings.Settings[keyName];
if (reportEngineKey != null)
{
result = reportEngineKey.Value;
}
}
return result;
}
}
Every time I tried to set the path for OpenWebConfiguration( ), I got the error "The relative virtual path is not allowed"
To make that scenario more testable, I usually take the approach of making a "settings manager" of my own, and giving it an interface. So for example:
public interface IConfig
{
string GetSettingValue(string settingName);
}
Then I can have my "real" implementation:
public sealed class Config : IConfig
{
public string GetSettingValue(string settingName)
{
// your code from your getKeyValue() method would go here
}
}
Then my code that uses it would take in an instance of this (this is an example of the Dependency Inversion Principal):
public void DoStuff(IConfig configuration)
{
string someSetting = configuration.GetSettingValue("ThatThingINeed");
// use setting...
}
So now for my production code, I can call DoStuff
and pass in an instance of Config
.
When I need to test, I can use a mocking tool (Moq, JustMock, RhinoMocks, etc) to create a fake IConfig
that returns a known value without hitting the actual .config file, or you can do it without a mocking framework by making your own mocks (and store them in your test project).
public class ConfigMock : IConfig
{
private Dictionary<string, string> settings;
public void SetSettingValue(string settingName, string value)
{
settings[settingName] = value;
}
public string GetSettingValue(string settingName)
{
return settings[settingName];
}
}
and
[Test]
public void SomeExampleTest()
{
var config = new ConfigMock();
config.SetSettingValue("MySetting", "SomeValue");
var underTest = new MyClass();
underTest.DoStuff(config);
}
The easiest way to do this is to use a mocking library such as moq. It takes a bit of time to figure it out, but once you do you can abstract away most of your plumbing to return the values you need for repeatable, consistent testing.