runtime: ConfigurationManager doesn't find config file with "dotnet test"

Hello,

When run with “dotnet test” and NUnit, the actual entry point is the “testhost”:

.nuget/packages/microsoft.testplatform.testhost/15.0.0/lib/netstandard1.5/testhost.dll

Then it is looking at the wrong place and with wrong name.

Program.cs

using System;
using System.Configuration;
using NUnit.Framework;

namespace test_run
{
	[TestFixture]
    class Program
    {
		/*
        static void Main(string[] args)
        {
			ShowAppSettings();
        }*/
		
		[Test]
		public void ShowAppSettings(){
			var appSettings = ConfigurationManager.AppSettings;

			if (appSettings.Count == 0)
			{
				Console.WriteLine("AppSettings is empty.");
			}
			else
			{
				foreach (var key in appSettings.AllKeys)
				{
					Console.WriteLine("Key: {0} Value: {1}", key, appSettings[key]);
				}
			}
			
			Assert.AreEqual(2, appSettings.Count);
		}
    }	
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="Setting1" value="May 5, 2014"/>
    <add key="Setting2" value="May 6, 2014"/>
  </appSettings>
</configuration>

csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
 <ItemGroup>
   <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0-preview2-25405-01" />
    <None Update="App.config">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </None>
	<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
    <PackageReference Include="NUnit" Version="3.7.1" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.8.0-alpha1" />
  </ItemGroup>
</Project>

EDIT: @karelz fixed code formatting

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 14
  • Comments: 29 (18 by maintainers)

Commits related to this issue

Most upvoted comments

+1 … also seeing this, following for a fix date.

EDIT: Our temporary workaround involved adding this to the test project’s *.csproj file which copies the app.config (you should already have this) to testhost.dll.config

<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
  <Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.dll.config" />
</Target>

We’re facing this issue too and it’s a blocker for our .net core migration. The easiest way to check is to have this inside your test code

var myConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;

And you’ll see that instead of referencing C:\myapp\bin\Debug\netcoreapp2.0\myapp.dll.config it references C:\myapp\bin\Debug\netcoreapp2.0\testhost.dll.config

What is the intended workaround? What about a patched release?

@karelz The author wants to load his app.config while testing, for any of a number of possible reasons. Maybe that’s the only way to initialize a component needed for the test, or maybe there are settings that need to be validated. In any case, consider a test project named MyTests. When you build, MyTests.dll and MyTests.dll.config appear in bin\Debug.

When you run VSTest, the entry assembly is testhost.dll. ConfigurationManager knows nothing about the NUnit VSTest adapter or VSTest itself and therefore it tries to load the entry assembly’s config as usual and loads testhost.dll.config from the folder which contains testhost.dll rather than loading MyTests.dll.config from the folder which contains MyTests.dll.

That means the test will fail because the configuration it directly or indirectly relies on is unavailable.

Here’s a snippet that should work for both x86 and x64 cases. Place this in your unit test global setup:

#if NETCOREAPP
using System.Configuration;
using System.IO;
using System.Reflection;
#endif

...

// In your global setup:
#if NETCOREAPP
    string configFile = $"{Assembly.GetExecutingAssembly().Location}.config";
    string outputConfigFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;
    File.Copy(configFile, outputConfigFile, true);
#endif

https://github.com/dotnet/corefx/issues/32095 created to find another solution.