How to mock ConfigurationManager.AppSettings with moq

Solution 1:

I am using AspnetMvc4. A moment ago I wrote

ConfigurationManager.AppSettings["mykey"] = "myvalue";

in my test method and it worked perfectly.

Explanation: the test method runs in a context with app settings taken from, typically a web.config or myapp.config. ConfigurationsManager can reach this application-global object and manipulate it.

Though: If you have a test runner running tests in parallel this is not a good idea.

Solution 2:

I believe one standard approach to this is to use a facade pattern to wrap the configuration manager and then you have something loosely coupled that you have control over.

So you would wrap the ConfigurationManager. Something like:

public class Configuration: IConfiguration
{
    public User
    {
        get
        { 
            return ConfigurationManager.AppSettings["User"];
        }
    }
}

(You can just extract an interface from your configuration class and then use that interface everywhere in your code) Then you just mock the IConfiguration. You might be able to implement the facade itself in a few different ways. Above I chose just to wrap the individual properties. You also obtain the side benefit of having strongly typed information to work with rather than weakly typed hash arrays.

Solution 3:

Maybe is not what you need to accomplish, but have you considered to use an app.config in your test project? So the ConfigurationManager will get the values that you put in the app.config and you don't need to mock anything. This solution works nice for my needs, because I never need to test a "variable" config file.

Solution 4:

You can use shims to modify AppSettings to a custom NameValueCollection object. Here is an example of how you can achieve this:

[TestMethod]
public void TestSomething()
{
    using(ShimsContext.Create()) {
        const string key = "key";
        const string value = "value";
        ShimConfigurationManager.AppSettingsGet = () =>
        {
            NameValueCollection nameValueCollection = new NameValueCollection();
            nameValueCollection.Add(key, value);
            return nameValueCollection;
        };

        ///
        // Test code here.
        ///

        // Validation code goes here.        
    }
}

You can read more about shims and fakes at, Isolating Code Under Test with Microsoft Fakes. Hope this helps.

Solution 5:

Have you considered stubbing instead of mocking? The AppSettings property is a NameValueCollection:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var settings = new NameValueCollection {{"User", "Otuyh"}};
        var classUnderTest = new ClassUnderTest(settings);

        // Act
        classUnderTest.MethodUnderTest();

        // Assert something...
    }
}

public class ClassUnderTest
{
    private readonly NameValueCollection _settings;

    public ClassUnderTest(NameValueCollection settings)
    {
        _settings = settings;
    }

    public void MethodUnderTest()
    {
        // get the User from Settings
        string user = _settings["User"];

        // log
        Trace.TraceInformation("User = \"{0}\"", user);

        // do something else...
    }
}

The benefits are a simpler implementation and no dependency on System.Configuration until you really need it.