I\'ve created a simple unit test project to read an app.config file. Target framework is Core 2.0. I also created a Core 2.0 console app, to sanity-check myself to make sure
.CORE 3.1 To find out what dll.config file was being used, I debugged the test by adding this line and looking to see what the value is.
string path = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;
Then I found out resharper was using testhost.dll.config and VStest was using testhost.x86.dll.config. I needed to add the following lines to the project file.
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.dll.config" />
<Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.x86.dll.config" />
</Target>
None of the answers given here provide a viable workaround when you're dealing with code accessing directly the static ConfigurationManager
properties such as AppSettings
or ConnectionStrings
.
The truth is, it is not possible at the moment. You can read through the discussion here to understand why: https://github.com/dotnet/corefx/issues/22101
There is talk to implement the support for it here: https://github.com/Microsoft/vstest/issues/1758
In my opinion it makes sense to support this scenario since it's been working on the .NET Framework plus System.Configuration.ConfigurationManager
is a .NET Standard 2.0 library now.
If you check the result of the call to ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
It should tell you where the required configuration file should be while running unit tests for that assembly.
I found that instead of having an app.config
file, ConfigurationManager was looking for a testhost.dll.config
file.
This was for a project targeting netcoreapp2.1
, with a reference to Microsoft.NET.Test.Sdk
,NUnit 3.11
and Nunit3TestAdapter 3.12.0
Add the configuration file
First, add a appconfig.json file to the Integration test project
Configure the appconfig.json file to be copied to the output directory by updating
Add NuGet package
Use the configuration in your unit tests
[TestClass]
public class IntegrationTests
{
public IntegrationTests()
{
var config = new ConfigurationBuilder().AddJsonFile("appconfig.json").Build();
_numberOfPumps = Convert.ToInt32(config["NumberOfPumps"]);
_numberOfMessages = Convert.ToInt32(config["NumberOfMessages"]);
_databaseUrl = config["DatabaseUrlAddress"];
}
}
A hacky, but working way is to copy the config to the same folder as an entry assembly, whatever it is:
[SetUpFixture]
public class ConfigKludge
{
[OneTimeSetUp]
public void Setup() =>
File.Copy(
Assembly.GetExecutingAssembly().Location + ".config",
Assembly.GetEntryAssembly().Location + ".config",
true);
[OneTimeTearDown]
public void Teardown() =>
File.Delete(Assembly.GetEntryAssembly().Location + ".config");
}
Apart from adding this class, the only thing to make it work is to include app.config
file in test project (without any copying options). It should be copied to the output folder as <your test project name>.dll.config
at the build step, because it's kind of default logic.
Note the documentation for OneTimeSetUpAttribute
:
Summary: Identifies a method that is called once to perform setup before any child tests are run.
Although it should work for parallel test runs for a single project, there could be obvious troubles when running two test projects simultaneously, since the config would get overwritten.
However, it is still suitable for containerized test runs, like in Travis.
For my mixed .NET-Core & .NET-Framework project, I added the following to the 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
This copies the config file to the output path testhost.dll.config
but should be resilient enough to account for future changes in the testing framework.
Or you can copy to below, which amounts to the same thing:
string outputConfigFile = Path.Combine(Path.GetDirectoryName(configFile), $"{Path.GetFileName(Assembly.GetEntryAssembly().Location)}.config");
Credit to @stop-cran and @PaulHatcher's solutions, this is a combination of those two.