Access App.Config Settings from Class Library Called through Unit Test Project - c#

I have the following setup:
ASP.net 3.5 Web Site Project
C# Class Library with business logic
C# Class Library for unit testing
The business logic library does all of the db access. It gets connection strings from the web.config file of the web site by accessing System.Configuration.ConfigurationManager.ConnectionStrings. When the library is called by the web site, this works fine, as the library looks for the config of the caller.
I want to be able to test my business logic through the unit testing class library. I have put an App.config file in the root of the testing class library. From what I read, when the testing library calls data access procedures that are part of the business logic library, the connection settings from the App.config file of the testing library should be accessed and used. However, when I try to run my unit tests, I am getting errors back that indicate that the testing library's App.config file (and/or its contents) is not being accessed successfully.
My retrieval of the config properties (from within the business logic library) looks like this:
public SqlConnection MainConnection {
get {
string conn = "";
try {
conn = System.Configuration.ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
} catch {
// might be calling from test project. Need to reference app settings
conn = System.Configuration.ConfigurationManager.AppSettings["connString"];
}
return new SqlConnection(conn);
}
}
When this is called from the website project, it works. From within the unit test, the conn variable is never set to anything (I have also tried System.Configuration.ConfigurationSettings.AppSettings, and using instead of with the same result). What do I need to do to make the business logic class library successfully retrieve the unit test class libraries settings, when called from within the NUnit GUI?

I just found the solution here. App.config is now being used properly when running my tests through the NUnit GUI.
Apparently if you are using the NUnit GUI and add the assembly by going through Project > Add Assembly, it doesn't access the app.config. However, if you add the assembly to the NUnit project by dragging the dll from Windows Explorer into the NUnit GUI, then it will access the app.config.
Alternatively, you can add the assembly through the GUI and then go in the NUnit GUI > Project > Edit, and set the Configuration File Name to the name of the configuration file (VS will set this to name.of.your.dll.config) and set the Project Base to the \bin\Debug directory of your project (these are the extra steps that are done in the background when you drag in the assembly vs adding it manually.

I'd recommend changing the design such that your business-logic layer, instead of having the responsibility to locate configuration settings, is injected with them.
Your Web app could inject settings it reads from its Web.config file, while your unit test could inject different settings (e.g. connection string to a test database, etc.)

Just rename app.config to name.of.your.dll.config. It works for me.

Try WebConfigurationManager.OpenWebConfiguration() method
Configuration config = WebConfigurationManager.OpenWebConfiguration(#"x:\path\web.config");
KeyValueConfigurationCollection appSettings = config.AppSettings.Settings;
string connString = appSettings["connString"].Value;

Related

Reading configuration from Web.config when Startup of WebAPI class is invoked from OWIN TestServer

We have an ASP.NET Web application that uses .net Framework 4.7.2 and I am supposed to develop integration tests for that app.
I have a problem with OWIN TestServer.
Our Api project uses ConfigurationManager to read settings from Web.config file, that is placed inside of that project. It successfully reads settings when i run the api project, but when i try to run my integration tests project, anytime when i try to read one of the values (example below), it returns null:
string test = ConfigurationManager.AppSettings["SomeSettingName"];
I did ctrl+f in Visual Studio to see if reading configuration from web.config file is explicitly configured somewhere, but i didn't find it. I tried to find in google how to to manually specify where that configuration is, but it doesn't help either:
ConfigurationManager.OpenExeConfiguration("C:\\Users\\myuser\\project\\full\\path\\OurApi\\Web.config");
string test = ConfigurationManager.AppSettings["SomeSettingName"];
It's still null. Does anyone have an idea how to fix this issue?

EntityFramework connection string in referencing project's web.config

I have two projects in my solution: an ASP.NET MVC web app project with a web.config per environment (production/UAT/dev) and another DAL class library project referenced by the web project that uses EntityFramework Database First to handle persistence. At the moment, the DAL class library project has its own App.Config that specifies the connection string to be used.
I require different connection strings (or rather, different data source) for the different environments.
How would I go about moving the connection strings to the web.config in the the web project and referencing them from the DAL project at runtime?
The auto-generated EF Model.Context.cs code that currently references the connection string name is [name changed for anonymity]:
public EodActivityEntities()
: base("name=DatabaseNameEntities")
{
}
Your application will only ever read a single app.config or web.config at run time which will be the one from your start-up project.
Therefore if you have the following in your DAL:
public EodActivityEntities()
: base("name=DatabaseNameEntities")
{
}
... and you run your web application as your start-up project, it will pick up the connection string with name DatabaseNameEntities from that project's web.config, ignoring what is in your DAL app.config. So it's already doing that for you. Therefore I would say that you shouldn't need to have your connection string in your DAL's app.config file at all.
Now, for the different environments you want different connection strings. Create new Solution Configurations for your environments DEV, UAT & LIVE and you can use web.config transformations (info here and here) and it will build with the correct connections strings.
I would recommend passing the connection string in the constructor of your context. The base constructor created by EF takes a string and can either be a named value from a configuration file or simply the connection string itself.
Then move your connection strings per environment to the MVC project where you can instantiate the context using values in it's web.config
var connectionString = WebConfigurationManager.AppSettings["connection"];
var context = new EodActivityEntities(connectionString);
Coulton is correct in that only one configuration file will be loaded, and a solution could be to name the connection strings the same so that the web.config will load when you run the application. However, this is spreading your configuration around rather than pushing that to the context root of the application.
When you reference your DAL project from your Web project, the built DAL.dll should automatically be copied into the /bin folder of your Web project at the time the Web project is built. First, check that is indeed happening. If not, look at the Web project References, find your DAL project in the list and view the properties. CopyLocal should be set to True.
When your Web project is running, any reference made by your DAL to settings that would have come from your DAL's app.config, will instead come from your Web app's web.config, as the DAL will be running under the context of the Web application.
So you are right, that you need to add settings to your web.config.
The best way to utilise different values for different environments is to use web.config transforms. In a Web application, you may already have a couple of these as child solution files sat under your web.config (web.debug.config & web.release.config). Visual Studio will apply these transformations when publishing. We typically have a publish profile for each environment and a matching transform file for each environment, but only one actual web.config file with all the default (untransformed) settings in.
You didn't mention which version of Visual Studio you are using, but this article may help you along the way:
http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/web-config-transformations
This explains further: http://go.microsoft.com/fwlink/?LinkId=125889

Base class not finding app settings

This is somewhat of a general question but I haven't found much by googling it. I have a test framework that sets up an environment for testing purposes. My application consumes this framework through a reference path and runs manual tests just fine. However, once I ask the build server to run my test the framework complains it cannot find any of my app settings. The app.config file sits in my testing project for my application and I am sure it exists in the correct bin folder on my build server. I'm doing this in a C# .NET environment.
EDIT:
I'm not sure what to be more specific about. I would imagine it's something with the build server since it seems to work running tests locally but I have no clue what to look at. Nothing else about the build server is failing, just getting the app settings.
The framework is .NET 4.0 while the main project is 4.5. I'm using nunit to run the tests and running them outside the build process but using the Nunit gui fails at the same point.
The code that grabs the app settings is pretty basic:
string databaseName = ConfigurationManager.AppSettings["databaseName"];
EDIT
Snippet of my test:
public class UserServiceTests : DeployDBEveryFixtureBase
{
public UserServiceTests()
{
DBSetup("Core");
DBSetup("Postal");
DBSetup("Common");
}
private UserService userService = new UserService(string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};",
ConfigurationManager.AppSettings["targetServer"],
ConfigurationManager.AppSettings["databaseName"],
ConfigurationManager.AppSettings["userID"],
ConfigurationManager.AppSettings["password"]));
[Test]
public void UserService_Get()
{
// Act
User user = userService.GetUser(Guid.Empty, "*****", string.Empty);
// Assert
Assert.IsTrue(user.FirstName == "System");
}
}
The environment deployment is in the base class of DeployDBEveryFixtureBase. The DBSetup calls ensure that each database is deployed in the proper order. All of those seem to run fine and my tests complete but I still get the described error. If I look at the database I can all the datbases being properly deployed and then removed (the base class includes a TestFixtureTearDown) but it seems like the build process is trying to run it again.
Note: I am only building the solution file during this process. I do not currently have a .proj file in the build.
Without knowing much about your build server or how exactly you run your tests there is only one issue which comes to mind, that is Shadow Copying. Can you check if your unit tested DLLs are not shadow copied to some location where the app.config file doesn't exist?
Apparently my testing framework had an empty constructor that wasn't so empty. It looks like the app.config was being properly queried but was returning an empty result set since the empty constructor did not have the proper arguments. After removing the contents of the empty constructor my test ran fine. Thank you all for the help.

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

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.

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