app.configs and MSTest Project - null reference for a connection string - c#

When I try to run Unit Tests (mstest) I run into this issue.
The line of code:
_mainCnStr = System.Configuration.ConfigurationManager.
ConnectionStrings["main"].ConnectionString;
Comes back as a null reference
It doesn't do this in the main UI project when I run it. What is the right method to get this connection string setting seen by the Unit Test project? I tried embedded as a resource. I tried Copy Always. What is the right combination of settings that will fix this for me?

One thing to watch with MSTest (from the IDE at least); it doesn't run the tests in the regular output (bin) folder, and it doesn't respect the project's file inclusions ("Copy to Output Directory"). You often need to explicitly tell it (MSTest) which files to put into the test area. You will need to include the "app.config" in this list; either via the testrunconfig ("Deployment"), or by adding an attribute ([DeploymentItem]) to the affected test fixtures.

You should add an app.config to the unit test project. It won't automatically use the settings in UI application's app.config.

I'm assuming mstests are, like nunit tests, embedded in a seperate assembly which gets loaded by the testing application? In that case, you may need to create some test set-up code which loads in the configuration file.

Related

C# - reading an app.config in MSTest / Unit tests

I'm trying to work out how to (and at the same time best practice) use an app.config file in unit tests (MSTest specifically).
So I have the actual project then a separate project. the actual project has an app.config - and it seems that the unit tests are using that file and not ones I am trying to specify.
I have tried the following:
Putting a copy of app.config in the root of the test project, removing some key config sections that are used within the code so thus should cause exceptions and failures - this doesn't seem to work
using
[DeploymentItem("app.config")]
Which I believe picks up the app.config from the test project root and deploys that?? Strangely, I also tried to change the path to
[DeploymentItem("Data\\app.config")]
Which is a directory I use to load other deployment items - however it complains that it cannot find the app.config.
What am I doing wrong here - and also am I doing it the right way (assuming I am missing something simple). I basically want a separate app.config where I can use specific test settings rather than use the real app.config copied or referenced.

Where Is This Configuration Coming From?

I am helping a team whose builds have started failing due to test failures.
The failures are being caused by missing connection string configuration. I checked the usual issues in respect of the config file to ensure that the connection string was specified with exactly the right name.
In the end I obtained the full path of the config file to check that the one on the build server contained the exact configuration that was expected.
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
The path did not point to the TestProject.exe.config file, but instead pointed to the vstest.executionengine.x86.exe.Config at the following location:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.executionengine.x86.exe.Config
This file contains no connection strings at all.
When I write out all of the available connection strings from configuration, I get the default connection string:
Name: LocalSqlServer Connection: data source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User
Instance=true . Aborting test execution.
This is coming from the machine.config file (kudos petelids).
So the big question is:
Why is the vstest.executionengine.x86.exe.Config being used rather than the app.config (at runtime TestProject.exe.config)? (I can guess that this is because the process running is the test runner, but I think it is fair to say that you would expect the test runner to let the test project use its own config file, which is what normally happens).
I think it is fair to say that you would expect the test runner to let the test project use its own config file, which is what normally happens
That's perfectly true assumption when working with NUnit, xUnit, etc. but not with Microsoft Test Runners (MSTest and VSTest). They simply ignore target assembly config file and use their own config.
There are two solution to this problem:
Change MSTest to NUnit or xUnit
Use custom config file (not the default one)
MSTest runs tests in isolated mode by default.
The solution to this issue was to add a new test project and move the tests into it.
The new project behaved like all of the other projects, running the tests in an isolated process and using the app.config file from the test project.
I'm putting this down to a quirk.

ConfigurationManager.GetSection(sectionName) returns null while performing unit tests

I have a unit tests project with it's own app.config file, which is a mock of a real configuration file defined by target project being tested. This mock file is loaded and processed by unit test code (not by target project), and it works properly if I run only tests within only this one test project.
ConfigurationManager.GetSection(sectionName)
However, if I run tests from several test projects, and other test projects are performed prior to relevant project, the above statement returns null. If discussed test project is performed as first, there is no problem with loading configuration file.
How can I fix loading of configuration file in unit test to work correctly?
Your problem is not ConfigurationManager.GetSection(sectionName) returns null, it is how can I test some code containing ConfigurationManager.GetSection(sectionName)?
And the answer is: wrap it, inject it, then for your test mock it.
You have several examples of pepole facing the same issue:
http://chrisondotnet.com/2011/05/configurationmanager-wrapper-for-unit-testing/
http://weblogs.asp.net/rashid/archive/2009/03/03/unit-testable-configuration-manager.aspx
(The second one is much more detailed, still the idea is the same).
Anyway, this is quite logical that you cannot use information from app.config in a unit test, as an app.config is contextual for the whole application, when it is required to write test absolutely independant. If you use directly an app.config value, then you have non logical coupling.
Facing the same issue this solved it:
app.config should be picked up inside a unit test if it's Copy to Output Directory property set to Copy if newer or if you add the DeploymentItem attribute [DeploymentItem("your.config")].
More detailed description:
http://social.msdn.microsoft.com/Forums/en-US/3e520735-8ced-4092-b681-38b69e0db534/unit-test-configuration#32998bf4-5a76-4083-99da-42f0c3a91559
similar question: MSTest and app.config issue
I think problem is either it could not find the file in test working directory or file itself failed to load.
I have solved this problem by explicitly loading configuration file with name. In your case you can try same.
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = #"d:\test\test.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
I used the test project post build command line, but remember to build the project if there are changes:
copy /Y "$(SolutionDir)$(SolutionName)\App.Debug.config" "$(TargetDir)$(ProjectName)$(TargetExt).config"

Problem with reflection in Unit/Integration tests

I´m dynamically creating an instance of a class with reflection and this works fine, except when trying to do this through unit testing - I´m using the MS testing framework.
I get the familiar error of: "Could not load file or assembly 'Assy' or one of its dependencies. The system cannot find the file specified"
I have copied the dll into the bin\debug bin of the Unit test project - is this not the correct place to put it?
string assyName = "Go.Data.SqlServer";
string typeName = "GoMolaMola.Data.SqlServer.DataProviderFactory";
Assembly assy = Assembly.Load( assyName );
object o = assy.CreateInstance( typeName );
Any ideas? I'm new to unit testing and any help would be appreciated.
Thanks
The bin/Debug folder is not where the unit tests run. Visual Studio will copy the output of your unit test compilation to a TestResults folder (typically keeping the last five test runs, each with a timestamp embedded in the folder name) and run the unit tests there.
If you want the .DLL in that folder, either create a reference to the .DLL from your test project, or use the DeploymentItem attribute to make sure the item is copied to the test directory.
I faced this problem too and none of the above answer worked for me :(
1. Adding reference to project doesn't work for me
2. Adding the DeploymentItem attribute also doesn't work
3. Adding the Post-Build command is also not possible in this case as Unit test engine is creating a new out directory each time with time stamp....and its searching that assembly in this new directory.
but I managed to solve this by enabling deployment and adding the specified file in Local Test Setting -->Deployment
For cases like this, when loading the DLL dynamically is needed from the Unit Testing, I have a post-build event that copies the DLL to that directory. I'd love to know if there's another way to do it. That was the only way that worked for me :(
To edit a Post-Build, right-click over the project, go to Build events, and place the copy, like this, in the Post-Build event command line:
copy $(TargetPath) "$(SolutionDir)yourDir\$(TargetFileName)"

Can a unit test project load the target application's app.config file?

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.
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!
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.
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());
}
}
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"
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");
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"
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.
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() {
}
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.
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)
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.
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.
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
In the unit test project, I renamed App.config to testhost.dll.config.
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.
And finally debugged my test and value from App.config:

Categories

Resources