161
votes

I am unit testing a .NET application (.exe) that uses an app.config file to load configuration properties. The unit test application itself does not have an app.config file.

When I try to unit test a method that utilizes any of the configuration properties, they return null. I'm assuming this is because the unit test application is not going to load in the target application's app.config.

Is there a way to override this or do I have to write a script to copy the contents of the target app.config to a local app.config?

This post kind-of asks this question but the author is really looking at it from a different angle than I am.

EDIT: I should mention that I'm using VS08 Team System for my unit tests.

11

11 Answers

63
votes

The simplest way to do this is to add the .config file in the deployment section on your unit test.

To do so, open the .testrunconfig file from your Solution Items. In the Deployment section, add the output .config files from your project's build directory (presumably bin\Debug).

Anything listed in the deployment section will be copied into the test project's working folder before the tests are run, so your config-dependent code will run fine.

Edit: I forgot to add, this will not work in all situations, so you may need to include a startup script that renames the output .config to match the unit test's name.

121
votes

In Visual Studio 2008 I added the app.config file to the test project as an existing item and selected copy as link in order to make sure it's not duplicated. That way I only have one copy in my solution. With several test projects it comes in really handy!

Add Existing Item

Add As Link

54
votes

Whether you're using Team System Test or NUnit, the best practice is to create a separate Class Library for your tests. Simply adding an App.config to your Test project will automatically get copied to your bin folder when you compile.

If your code is reliant on specific configuration tests, the very first test I would write validates that the configuration file is available (so that I know I'm not insane) :

<configuration>
   <appSettings>
       <add key="TestValue" value="true" />
   </appSettings>
</configuration>

And the test:

[TestFixture]
public class GeneralFixture
{
     [Test]
     public void VerifyAppDomainHasConfigurationSettings()
     {
          string value = ConfigurationManager.AppSettings["TestValue"];
          Assert.IsFalse(String.IsNullOrEmpty(value), "No App.Config found.");
     }
}

Ideally, you should be writing code such that your configuration objects are passed into your classes. This not only separates you from the configuration file issue, but it also allows you to write tests for different configuration scenarios.

public class MyObject
{
     public void Configure(MyConfigurationObject config)
     {
          _enabled = config.Enabled;
     }

     public string Foo()
     {
         if (_enabled)
         {
             return "foo!";
         }
         return String.Empty;
     }

     private bool _enabled;
}

[TestFixture]
public class MyObjectTestFixture
{
     [Test]
     public void CanInitializeWithProperConfig()
     {
         MyConfigurationObject config = new MyConfigurationObject();
         config.Enabled = true;

         MyObject myObj = new MyObject();
         myObj.Configure(config);

         Assert.AreEqual("foo!", myObj.Foo());
     }
}
24
votes

If you have a solution which contains for example Web Application and Test Project, you probably want that Test Project uses Web Application's web.config.

One way to solve it is to copy web.config to test project and rename it as app.config.

Another and better solution is to modify build chain and make it to make automatic copy of web.config to test projects output directory. To do that, right click Test Application and select properties. Now you should see project properties. Click "Build Events" and then click "Edit Post-build..." button. Write following line to there:

copy "$(SolutionDir)\WebApplication1\web.config" "$(ProjectDir)$(OutDir)$(TargetFileName).config"

And click OK. (Note you most probably need to change WebApplication1 as you project name which you want to test). If you have wrong path to web.config then copy fails and you will notice it during unsuccessful build.

Edit:

To Copy from the current Project to the Test Project:

copy "$(ProjectDir)bin\WebProject.dll.config" "$(SolutionDir)WebProject.Tests\bin\Debug\App.Config"
9
votes

This is a bit old but I found a better solution for this. I was trying the chosen answer here but looks like .testrunconfig is already obsolete.

1. For Unit Tests, Wrap the config is an Interface (IConfig)

for Unit tests, config really shouldn't be part of what your testing so create a mock which you can inject. In this example I was using Moq.

Mock<IConfig> _configMock;
_configMock.Setup(config => config.ConfigKey).Returns("ConfigValue");
var SUT = new SUT(_configMock.Object);

2. For Integration test, dynamically add the config you need

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if(config.AppSettings.Settings[configName] != null)
{
    config.AppSettings.Settings.Remove(configName);
}
config.AppSettings.Settings.Add(configName, configValue);
config.Save(ConfigurationSaveMode.Modified, true);
ConfigurationManager.RefreshSection("appSettings");
5
votes

This is very easy.

  • Right click on your test project
  • Add-->Existing item
  • You can see a small arrow just beside the Add button
  • Select the config file click on "Add As Link"
4
votes

If you are using NUnit, take a look at this post. Basically you'll need to have your app.config in the same directory as your .nunit file.

2
votes

If you application is using setting such as Asp.net ConnectionString you need to add the attribute HostType to your method, else they wont load even if you have an App.Config file.

[TestMethod]
[HostType("ASP.NET")] // will load the ConnectionString from the App.Config file
public void Test() {

}
0
votes

I use NUnit and in my project directory I have a copy of my App.Config that I change some configuration (example I redirect to a test database...). You need to have it in the same directory of the tested project and you will be fine.

0
votes

I couldn't get any of these suggestions to work with nUnit 2.5.10 so I ended up using nUnit's Project -> Edit functionality to specify the config file to target (as others have said it needs to be in the same folder as the .nunit file itself). The positive side of this is that I can give the config file a Test.config name which makes it much clearer what it is and why it is)

0
votes

Your unit tests are considered as an environment that runs your code to test it. Just like any normal environment, you have i.e. staging/production. You may need to add a .config file for your test project as well. A workaround is to create a class library and convert it to Test Project by adding necessary NuGet packages such as NUnit and NUnit Adapter. it works perfectly fine with both Visual Studio Test Runner and Resharper and you have your app.config file in your test project. enter image description here

enter image description here

enter image description here

enter image description here

And finally debugged my test and value from App.config:

enter image description here