3

What I'm using

I'm using:

  • .NET 6 with <Nullable>disable</Nullable>,
  • NUnit (3.13.3),
  • and System.Configuration.ConfigurationManager.

What I have

Currently, I have a simple solution consisting of 3 projects:

  • A class library,
  • a console app,
  • and a unit test project

The class library has a single class Foo which uses ConfigurationManager to read setting from configuration file

using System.Configuration;

namespace ClassLibrary;

public class Foo
{
    public static string Bar = ConfigurationManager.AppSettings["setting"];
}

App.Config is located in the solution root, it's linked to each project and looks like this

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="setting" value="Kitty meow" />
  </appSettings>
</configuration>

When I use the Foo class in console app the setting value is read from the file just fine

using ClassLibrary;

Console.WriteLine(Foo.Bar); // Bar property contains the correct value
Console.ReadKey();

However, when I try to use the Foo class in unit test, the value of Bar property is null

using ClassLibrary;
using NUnit.Framework;

namespace TestProject;

public class ConfigurationManagerTest
{
    [Test]
    public void MakeSureThatConfigurationManagerReadsFromFileCorrectly()
    {
        Assert.That(Foo.Bar, Is.Not.Null); // Bar property is null
    }
}

The full source is available on GitHub:

https://github.com/dva-meow/UnitTestConfiguration

What I have tried

I've been trying to figure out what was causing this but had no success. Here's a list of what I've tried:

1. Copying the configuration fileIn this SO post as well as in this one a few people mention that it's necessary to link/copy the App.Config file to the unit test project. This is working for the console app but not for the unit test (I've tried both linking and copying the file).

2. Making sure the configuration file is present in the executing directoryThis SO answer says that:

When you compile an application, its app.config is copied to the bin directory with a name that matches your exe. For example, if your exe was named "test.exe", there should be a "text.exe.config" in your bin directory.

I made sure this was indeed the case for my project and I can confirm, that the renamed App.Config file is being copied to the bin directory of each project.

3. Investigating when initialization of static field occurThis SO answer suggests that:

Static classes are initialized prior to first use of any static member of that class. Unit Test code is no exception to this rule.

I was experimenting in debug for a while but haven't discovered anything useful. The correct value is present in the console app while in unit test it's always null, regardless of how many times I try to access the Bar property. (Also, I find this a bit odd as I don't believe it matters at all whether I assert the property for null right away or assign it to a variable before doing it.)

4. Experimenting with case-sensitivity — I tried renaming the configuration file to rule out the possibility that the ConfigurationManager is case-sensitive when used in unit tests.

What I need

I could probably come up with some sort of a workaround to avoid this issue but I would very much like to get to the bottom of this. All circumstances seem to be the same for both the console app as well as the unit test project and I'm really confused why it's not working the same in both cases.

What am I doing wrong?

dva
  • 303
  • 1
  • 2
  • 12
  • small question - why do you use old configuration approach in .NET6? It is common now to use appsettings.json + [IConfiguration](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0 "RTFM"). So, it seems you to dig a wrong hole in a wrong direction. In modern approach you can explicitly set IConfigurationBuilder to use any json file you want. – Ryan Aug 22 '22 at 14:45
  • Although you make a fair point I just wanted to try the old approach first. I'm aware of the existence of IConfigurationBuilder approach, however, since I've never really set up a new app from scratch using any of them I've figured I would start with the old approach and then potentially move to the newer one. – dva Aug 22 '22 at 14:58
  • Ok, it's up to you then solving weird problems while digging in wrong direction. Btw, i believe solution lies somewhere in second option you tried (making sure the configuration file is present in the executing directory) – Ryan Aug 22 '22 at 15:21

2 Answers2

1

Simple. You have an App.config but you aren't running your app. You are running NUnit. Each NUnit test assembly may have a config file of its own and you have to follow NUnit conventions rather than .NET conventions to make sure the config is used.

In this case, rename your config based on your test assembly name: e.g. my.test.assembly.dll.config and make sure it's in the same directory as the assembly.

See this (ancient but still basically correct) blog post for a more detailed explanation: http://charliepoole.org/technical/how-nunit-finds-config-files.html

Charlie
  • 12,928
  • 1
  • 27
  • 31
  • 2
    Unfortunately, I already have the file present in the directory. (I have actually mentioned that in point 2 of what I have tried. Maybe I should have been been more thorough with the description.) My test project is called TestProject and the files are in the following directory: UnitTestConfiguration\TestProject\bin\Debug\net6.0. In this directory there's both an assembly TestProject.dll and the renamed configuration file TestProject.dll.config as well as other stuff of course but it doesn't work regardless of that – dva Aug 23 '22 at 07:41
0

I've the same issue: UniTests targeting .net6.0, and a class library I want to test in netstandard 2.0. It seems like ConfigurationManager is unable to load the configuration files.