172

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.

Community
  • 1
  • 1
Jordan Parmer
  • 36,042
  • 30
  • 97
  • 119

12 Answers12

130

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

bbodenmiller
  • 3,101
  • 5
  • 34
  • 50
  • 8
    Perfect answer, simple and objective! +1 – Custodio Feb 05 '10 at 19:36
  • 3
    This is the best solution and should be marked as the answer. – niaher Mar 06 '13 at 06:50
  • 5
    For adding existing item "as a link" you should: "In the Add Existing Item dialog box, locate and select the project item you want to link", then: "From the Open button drop-down list, select Add As Link." – uriel May 17 '15 at 08:26
  • This worked great for me. I'm trying to think of a situation where it would not work... And I've thought enough now. Thanks! – Dudeman3000 Apr 03 '19 at 22:28
  • 1
    This do not work for me. I've added a link to app.config, but when I Debug Tests, the file used is "Learn.Printers\Learn.Printers.Tests\bin\Debug\net6.0\testhost.dll.config" instead of "Learn.Printers\Learn.Printers.Tests\bin\Debug\net6.0\Learn.Printers.Tests.dll.dll.config". The second file is present in dir, but not the first file – Glauco Cucchiar Sep 15 '22 at 14:40
  • doesn't work for me in VS 2022 (.Net 6). – Ritesh Jan 16 '23 at 18:27
64

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.

Jeromy Irvine
  • 11,614
  • 3
  • 39
  • 52
  • 9
    It's a lot easier to just add an app.config fiel to the test project -- you then don't need to play around with the .testrunconfig at all. – Rowland Shaw Jan 14 '09 at 12:20
  • 13
    @Rowland if you do that, you have to maintain two copies of app.config. I'd rather spend 10 seconds, once, using the .testrunconfig tool than having to remember to update the app.config in both places. – Jeromy Irvine Jan 15 '09 at 06:22
  • 72
    Can't you just add a non-copying reference? (Add Existing Item...) – EFraim Nov 10 '10 at 06:39
  • 8
    EFraim's comment should be the accepted answer, this is much simpler than anything else. – reggaeguitar Feb 05 '14 at 19:38
  • 30
    For EFraim's soln: Be sure to use the "Add as Link" from the command button. Otherwise you still get a copy. Also, although the question is specifically for a .Net app, this won't work for a web app as a web app's config has the wrong name (Web.Config, not App.Config) – Rob Von Nesselrode Jan 15 '15 at 04:35
  • @reggaeguitar there is no option to accept a comment as answer. – Sebastian Sep 14 '15 at 12:36
  • 3
    EFraim's answer is NOT the correct answer. Here's why: Under unit test conditions you might want the settings to be other than the default settings published. If you are tweaking your default settings just to measure the response of a unit test, then you may very well forget to undo those settings later when you publish. IMHO this is bad. The unit test should have its own copy and you should systematically change or update those settings according to your unit test goals. – user3524983 Jun 29 '17 at 14:46
  • Sorry, I don't have an **app.config** because I don't have an EXE. Only a DLL and it doesn't have a .config file. I just want to create one just for my Unit Test. So should I name it as `.config`? TIA – Pap Jun 12 '19 at 11:04
57

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());
     }
}
dhinesh
  • 4,676
  • 2
  • 26
  • 44
bryanbcook
  • 16,210
  • 2
  • 40
  • 69
  • 2
    I agree with the spirit of passing in the configuration dependency here, this seems to have been answered, by Mark Seemann no less! over here: [Failing unit tests due to missing .config file](http://stackoverflow.com/questions/7288859/ways-of-keeping-configuration-code-out-of-logic-code-using-dependency-injection) – Shaun Aug 02 '12 at 14:43
  • There is a " missing from the line: string value = ConfigurationManager.AppSettings["TestValue]; I tried to fix it, but would have had to find a further 5 characters to fix to get stackoverflow to allow me to make an edit. – Jane Oct 29 '12 at 12:18
25

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"
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
Antti
  • 1,029
  • 12
  • 15
  • Really nice solution. This helped me avoid copying and duplicating `.config` files. Thanks for sharing! :) – Leniel Maccaferri Aug 07 '14 at 21:04
  • Very nice solution! Thanks a lot. – Vin Shahrdar May 31 '17 at 21:16
  • Nice solution, but what happens when the main `web.config` only have references to external `.config` files within the same project. As the path can only point to folders within the same directory (which is true normally), when running tests, it will not be able to handle those external files. Any idea how to solve it? – Sugafree Jun 13 '18 at 07:37
  • This worked for me: copy "$(SolutionDir)\MainProject\Web.config" "$(ProjectDir)app.config" – Andrew Jul 23 '19 at 16:06
10

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");
MichaelChan
  • 1,808
  • 17
  • 34
5

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"
Hari Das
  • 10,145
  • 7
  • 62
  • 59
4

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.

Cory Foy
  • 7,202
  • 4
  • 31
  • 34
2

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() {

}
Zyo
  • 1,934
  • 21
  • 25
1

In my case, I performed the following steps to resolve my issue. I'm using Visual Studio Professional 2022, NUnit 3.13.3 and .NET 6.

  1. I added an App.config file to the test project per the suggestions but ConfigurationManager.AppSettings still did not load any of my app settings.

  2. In my unit test, I evaluated the value of ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None).FilePath and determined that it was looking for a file named testhost.dll.config

  3. In the unit test project, I renamed App.config to testhost.dll.config.

datchung
  • 3,778
  • 1
  • 28
  • 29
0

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)

Jane
  • 1,953
  • 1
  • 20
  • 27
0

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.

Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341
-1

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

Ben
  • 953
  • 12
  • 27