3

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"

2 Answers 2

2

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);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Also note that this is just 1 way of making this testable. It is by no means the only way. There are also mocking frameworks out there that can mock static methods, and you could use one of those to mock out your existing Config.getKeyValue() method, with little to no other code changes.
I would add that the answer below by kprobst goes hand in hand with this answer. Make the interface, then use the Moq library (or another mocking framework) to build the mock object that ConfigMock serves in this answer.
Thanks! It seems to be a clean and reusable approach.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.