Cannot Use ConfigurationManager inside Unit Test Project - c#

I'm trying to write a unit test for my project, but it will not let me use the Configuration Manager. Right now my project is set up like
ASP.Net application (all aspx pages)
ProjectCore (all C# files - model)
ProjectTest (all tests)
in my ProjectCore, I am able to access the ConfigurationManager object from System.Configuration and pass information onto the project. However, when I ran a test where the ConfigurationManager is involved, I get the error
System.NullReferenceException: Object reference not set to an instance of an object.
Here is an example of the test
using System.Configuration;
[TestMethod]
public void TestDatabaseExists()
{
//Error when I declare ConfigurationManager
Assert.IsNotNull(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString
}
in my other tests, ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString is what I set my data adapter's configuration string to, and returns a null error on the tests but not when I actually use the website. Any ideas?

It could be one of several issues:
You didn't add app.config to your ProjectTest project.
You didn't add connection string in your app.config.

You are doing a unit test and in unit test your concentration should be the particular method trying to test and should remove extraneous dependencies. in this case, try mocking/moleing(use Microsoft Mole and Pex) system.configuration class; that will give a solution for sure.
What I am saying, once you install MS moles-and-pex -> in your test project solution -> right-click the system assembly and choose create mole.
That will give you a mole'ed version of configuration class which in turn will have a mocked version of configuration class -- using which you can bypass the problem you are facing.

You also can use special configuration paths with the ExeConfigurationFileMap:
// Get the machine.config file.
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
// You may want to map to your own exe.config file here.
fileMap.ExeConfigFilename = #"C:\test\ConfigurationManager.exe.config";
// You can add here LocalUserConfigFilename, MachineConfigFilename and RoamingUserConfigFilename, too
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

It is related to the /noisolation parameter in the command line of mstest.exe.
Omitting the /noisolation parameter, it works.

first of all you must make sure that you have an app.config file in your nunit tests project.
To add it, you can open the project properties (right click on the project)
Enter the details of your connection, it will generate a app.config file or add the right section within :
In your Test class, add the reference to : System.Configuration;
=> using System.Configuration;
For example you could use your connectionString by this way :
[TestFixture]
public class CommandesDALUnitTest
{
private string _connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
[Test]
public void Method_Test()
{
string test = _connectionString;
....
}
}

Related

Specflow - Create Pre-defined data to be shared between all scenarios in test execution with parallel execution

I am trying to Re-create my BeforeTestRun step to run my setup only once per whole execution not per thread.
I had a look a Custom Deployment steps I have implemented some already but For my setup i need to bring in some values from the app.config file I am trying something like this
my Default.srprofile file contains:
<DeploymentTransformation>
<GlobalSteps>
<Custom type="Test.CustomDeploymentStep, Test"></Custom>
</GlobalSteps>
</DeploymentTransformation>
and my CustomDeploymentStep.cs:
public class CustomDeploymentStep : IDeploymentTransformationStep
{
public static string baseUrl;
public void Apply(IDeploymentContext deploymentContext)
{
baseUrl = ConfigurationManager.AppSettings["URL"];
}
public void Restore(IDeploymentContext deploymentContext)
{
DoSomething();
}
}
My app config contains the following:
<add key="URL" value="http://google.com" />
But That does not work, The ConfigurationManager.AppSettings only returns one key and one value
"key" : "TestProjectRetargetTo35Allowed" "value":"true"
How can I load my configuration from app.config into the Apply() method in CustomDeploymentStep?
Also If there is a better/more efficient way of generating pre-defined data in specflow with thread safe execution, please do let me know
I ran into the same problem once I needed to use custom deployment steps in more than one project in a large solution. This appears to be a bug within the TechTalk.SpecRun.Framework. The error is likely "Error applying global deployment step. Global steps cannot contain test assembly specific settings." and if you look inside the TestAssembly while debugging you will see the TestAssemblyConfigFilePath is null and/or swallowing another exception.
It doesn't register a project specific configuration file. My workaround was to save the config file into debug and access what I need like so:
string appConfigFilePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\App.config";
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = appConfigFilePath;
var config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
var baseUrl = config.AppSettings.Settings["URL"].Value;

Is it possible to add a new dependency to a .dll without changing the source code?

I have two dotnetcore2.1 projects. First project calls a method of the second project via reflection.
using System;
using System.Reflection;
namespace experiment1
{
class Program
{
static void Main(string[] args)
{
Type _type = Type.GetType("experiment2.Program");
object _object = Activator.CreateInstance(_type);
MethodInfo info = _type.GetMethod("SecondProjectsMethod");
info.Invoke(_object, new object[]{});
}
}
}
I can't give any reference to the Second Project nor changes its code. How can I make this call successfully without adding a Reference to the First Project? I tried to add records to the first project's deps-file and execute the first program like this:
dotnet exec --depsfile experiment1.deps.json experiment1.dll
It didn't work. Is it even possible to do this by changing deps-file or any other config? Or should I manipulate .dll file somehow? Which direction I should go?
You can manually load the assembly by calling:
Assembly.Load("experiment2");
It should look for the assembly in the current folder, or use the deps file to locate it. After that, you should be able to use Type.GetType just fine.
If you want to specify the full path to the assembly, use AssemblyLoadContext.Default.LoadFromAssemblyPath instead.
You can refer to this page for more information on the different ways of loading an assembly in .net core.

Load file during Unit Test in Unity3d's Unity Test Runner

Using Unity 2018.1.1f1 and Visual Studio Community 2017
I've been creating unit tests using unity's built in Test Runner. In this particular unit test, I want to read a file's content into a string. Without having to build a static path to the file (which will sit next to the unit test class itself), how can I reference it?
The folder structure looks like this:
Directory:
Assets/Plugins/MyTools/Common/Properties/_tests/
Files:
MyTools.Common.Properties.Tests.asmdef
PropertiesTests.cs
test.txt
test-prop-file.txt
The test and some output details:
namespace MyTools.Common.Properties.Tests {
public class PropertiesTests {
[Test]
public void ParsePropsFile() {
Debug.Log(Assembly.GetExecutingAssembly().GetName());
// MyTools.Common.Properties.Tests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Debug.Log(GetType().Assembly.GetManifestResourceNames().Length);
// 0
Debug.Log(Assembly.GetExecutingAssembly().GetManifestResourceNames().Length);
// 0
}
}
}
In visual studio, I've tried to set the properties (Build Action = Embedded Resource, and Copy to Output Directory = Copy Always) of test-prop-file.txt and test.txt but they do not seem to do anything. Also, when I close VS and reopen it, these are set back to what they were before (None and Do Not Copy). I've also tried other combos like Build Action = Resource or Content but still nothing.
So how can I go about loading these files in the unit test without referencing them directly with a static path like D:/Code/Unity/MyProject/Assets/Plugins/MyTools/Common/Properties/_tests/test.txt?
The location of your current test assembly can be retrieved with:
TestContext.CurrentContext.TestDirectory
(If I've remembered correctly - the middle 'CurrentContext' may not be necessary!)

Trying to nunit test enterprise logging

I'm trying to nunit test enterprise logging to proove creating of log etnries etc..
I cant seem to get it to work- I get an error the config section for loggin can not be found in config source - I think this has something to do with the fact that this is a wpf and the app config isnt being started when i run an nunit test from a class. Any thoughts?
namespace Nunit
{
[TestFixture]
public class NunitTests
{
string Path = #"C:\Users\dani\bin\Debug\trace.log";
[Test]
public void TestLogCreation()
{}
}
When you run NUnit executable, it tries to look into it's own config file for any configuration entries which it can't find. After that it searches for configuration entries in machine.config file. There also it does not find the config entries, hence it gives the error.
You can fix this by putting config entries in machine.config file.
But it would not be a right way to unit test. You have to provide fake class for reading configuration entries rather than reading actual config values from config file.
machine.config file can be found at below mentioned paths:
32 bit
%windir%\Microsoft.NET\Framework\[version]\config\machine.config
64 bit
%windir%\Microsoft.NET\Framework64\[version]\config\machine.config
EDIT
public interface IConfigReader
{
string ReadConfigEntry(string keyName);
}
public class ConfigReader : IConfigReader
{
public string ReadConfigEntry(string keyName)
{
return System.Configuration.ConfigurationManager.AppSettings[keyName];
}
}
public class FakeConfigReader : IConfigReader
{
public string ReadConfigEntry(string keyName)
{
string configValue = string.Empty;
//provide dummy implementation instead of reading actual .config file
return configValue;
}
}
Now create instances of IConfigReader interface. In actual code use ConfigReader implementation to read config values and while unit testing use FakeConfigReader implementation. In FakeConfigReader you can return any arbitrary hard coded value from ReadConfigEntry method.
Much easier way to accomplish this would be to create an app.config file within the Nunit project and copy the contents over - works perfectly

Using the connectionstring in an nunit test

we use the nunit.exe application to run our (integration)test
Now i experience the problem that the connectionstring is not picked up from the app.config from the dll where the testcode is in.
That sounds logical because the nunit.exe is the starting app and not the test dll (it used to work when i started the tests from the visual studio testframework by the way), but should i put the connectionstrings in the nunit.exe.config?
I tried setting them in the testcode (works for the appsettings : ConfigurationManager.AppSettings.Set("DownloadDirectory", mDir);) like this:
ConfigurationManager.ConnectionStrings.Add(conset); (where conset is a ConnectionStringSettings object), but then i get the error that the connectionstrings section is readonly.
What should i do to use the connectionstrings in my test?
EDIT:
we use the entity framework so we can't put the connectionstring in the appsettings because it reads from the section directly, i couldn't find a way to work around this behaviour.
Using reflection, you can (in memory) change your value of the Configuration.ConnectionStrings[connectionName], which in your case you would probably do in SetUp or perhaps TestFixtureSetUp. See http://david.gardiner.net.au/2008/09/programmatically-setting.html.
// Back up the existing connection string
ConnectionStringSettings connStringSettings = ConfigurationManager.ConnectionStrings[connectionName];
string oldConnectionString = connStringSettings.ConnectionString;
// Override the IsReadOnly method on the ConnectionStringsSection.
// This is something of a hack, but will work as long as Microsoft doesn't change the
// internals of the ConfigurationElement class.
FieldInfo fi = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(connStringSettings, false);
// Set the new connection string value
connStringSettings.ConnectionString = connectionStringNeededForNUnitTest;
I realize this is not the answer you are looking for, but it is the one I applied to solve your same problem:
You can modify, in EF5 and EF4.3 at least, your DbContext implementation and add a constructor that accepts a hard coded connection string, such as this:
public partial class MyContext : DbContext
{
public MyContext() : base("name=MyContext")
{
}
// --- Here is the new thing:
public MyContext(string entityConnectionString) : base(entityConnectionString)
{
}
// --- New thing ends here
// .... the rest of the dbcontext implementation follows below
}
You would have to paste this thing in every time you regenerate your context, but IMHO it's worth the hassle. The connection string has to be entity framework formatted with your metadata and everything, but you will be able to figure it out. Just keep it somewhere so you can paste it in whenever necessary.
You can read Connection String Value from ConfigurationManager.AppSettings, yes it is readonly. You can change it in App.Config.
If you want to change some values in connection string, for ex URL, in code you can change your dataContext.URL or any properties you want with coding.
I think for unit tests it may be much easy. you may put connection string into a test class directly as hardcoded string. in simple unit tests you test limited logic scope and not care of authentically of input arguments

Categories