NUnit Test a EXE and EXE's "ConfigurationManager.AppSettings" not working - c#

I want to understand a proper way of handling the scenario below
I have C# Solution which has two projects
One project is HelloWorld
and another project is TestHelloWorld
HelloWorld project read the config using ConfigurationManager.AppSettings["Message"].ToString()
And TestHelloWorld project is the NUnit project to test the HelloWorld project.
When the job being run from NUnit, the code of reading config is not working. Because it tried to read config from TestHelloWorld.config instead of HelloWorld.exe.config.
Can someone please provide some good practice of handling this.
I attached a graphic of my source code and also put the code below, appreciate people if you can download the code and have a try.
Thanks
Program.cs code as below
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
WordToSay wts = new WordToSay();
Console.WriteLine(wts.WordText());
Console.ReadLine();
}
}
public class WordToSay
{
public string WordText()
{
return ConfigurationManager.AppSettings["Message"].ToString();
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings >
<add key ="Message" value ="Hello"/>
</appSettings>
</configuration>
Class1.cs code as below
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using HelloWorld ;
namespace TestHelloWorld
{
[TestFixture]
public class Class1
{
[Test]
public void TestHello()
{
WordToSay wts = new WordToSay();
StringAssert.AreEqualIgnoringCase("Hello", wts.WordText ());
}
}
}

If your unit tests are designed to test the code, then don't depend on the config file at all. Extract your dependency out of your classes and use dependency injection to inject the data in. That way, you can stub your configuration class.
Alternatively, just add an app.config file to your unit testing project that contains the relevant information.
EDIT:
You can also look over this post Reload app.config with nunit

Related

How can I add a static 'Main' method suitable for an entry point?

I am getting an error on my code that says "Error CS5001
Program does not contain a static 'Main' method suitable for an entry point"
I am coding in C# using Microsoft Visual Studio and .NET. This is my code.
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
class projectsummer
{
[CommandMethod("OpenDrawing", CommandFlags.Session)]
public static void OpenDrawing()
{
string strFileName = "C:\\DRAFT.dwg";
DocumentCollection acDocMgr = Application.DocumentManager;
if (File.Exists(strFileName))
{
acDocMgr.Open(strFileName, false);
}
else
{
acDocMgr.MdiActiveDocument.Editor.WriteMessage("File " + strFileName +
" does not exist.");
}
}
}
I am not sure how to go about this error. Thank you!
Looking at this post and your previous question, let's try and break down what's going on.
You created a new Console application in Visual Studio. You did not tick "Do not use top level statements". This gave you a Program.cs file that was essentially empty (there was no "Main" method visible).
You erased the Hello World code given to you, and went to make a static method - the code from your previous question.
Damien_The_Unbeliever commented that based on the error, you put your method inside a "top level statement" file, and to put your method inside a class.
You wrap your method (which is still inside Program.cs) in a class, and now suddenly you get a Can't Find Entry Point error.
User Ryan Pattillo posted a great explanation of the original issue - where your method was "by itself" in the Program.cs file. You should follow their advice, but you should also ensure that this class is in its own file.
You should end up with this:
Program.cs
// this is the entire contents of the file
using ConsoleApp1;
ProjectSummer.OpenDrawing();
ProjectSummer.cs
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
namespace ConsoleApp1
{
public class ProjectSummer
{
[CommandMethod("OpenDrawing", CommandFlags.Session)]
public static void OpenDrawing()
{
// ...
}
}
}
Change ConsoleApp1 to the name of your project.
The entry point of your application, which right now is the only file that has "top level statements", remains Program.cs, thus you fix the Can't Find Entry Point error.
Another adjustment you can make, which seeing you're new to C# might be useful, is to not use top level statements at all. Modify your Program.cs to this:
namespace ConsoleApp1
{
internal static class Program
{
// this is your program's entry point
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
ProjectSummer.OpenDrawing();
}
}
}
Change ConsoleApp1 to the name of your project.
You cannot use the AutoCAD .NET API out of process. To be able to use the AutoCAD .NET libraries, you have to build a "class library" project (DLL) and NETLOAD this DLL from a running AutoCAD process. See this topic about in-process vs out-of-process and you can start from this other one to see how to create an AutoCAD .NET project.

Integrate C++ .dll wrapped by SWIG to C# project

I have 2 solutions under VS2019: RLibrary (contains C++ project) and VTApp (contains C# project).
Solution RLibrary has two projects: RLib C++ .dll and SwigW (wrapper project).
SwigW generated the following files: RLibCSHARP_wrap.cxx, RLib.cs, RLib.i and RLibPINVOKE.cs.
In the RLibPINVOKE.cs I have lines like:
class RLibPINVOKE {
//...
static RLibPINVOKE() {
}
[global::System.Runtime.InteropServices.DllImport("SwigW", EntryPoint="CSharp_new_Create")]
public static extern global::System.IntPtr new_Create();
[global::System.Runtime.InteropServices.DllImport("SwigW", EntryPoint="CSharp_new_Request")]
public static extern global::System.IntPtr new_Request();
// ...
}
So, after building RLibrary solution I will have two .dll (also .lib) files: RLib.dll and SwigW.dll.
I want to use new_Create(), new_Request() functions from the VTApp.
VTApp has two projects as well: UI and Core. UI has a reference to Core. I added RLibPINVOKE.cs file to the Core project by just Right Click->Add->Existing item and tried to use above mentioned functions from the UI project within namespace UI, i.e.,
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using Core;
using Newtonsoft.Json;
namespace UI {
public partial class MainWindow {
private void Execute_Req(object sender, EREventArgs e)
{
//...
IntPtr p = new_Create();
}
}
}
Unfortunately, I am getting CS01013: The name 'new_Create' does not exist in the current context. error.
In my opinion, even without adding SwigW.dll to the Core project I shouldn't have had this kind of compile time error. So, what is the problem here? How can I add SwigW.dll into the Core project properly if I need to add it? Also, should I add RLib.dll to the Core as well?
Try RLibPINVOKE.new_Create(). The method is inside a class RLibPINVOKE
class RLibPINVOKE {
//...
You'll perhaps need a using, but the Visual Studio should be able to suggest it to you on the RLibPINVOKE.

Is it possible to use 'HttpRuntime' in a NUnit project?

I'm following a guide to write output data from Visual Studio into a google spreadsheet. I'm using a NUnit project type for test-automation purposes.
At the end of the guide there is a code block that I pasted inside my project:
using OpenQA.Selenium.Support.UI;
using System;
using NUnit.Framework;
using OpenQA.Selenium;
using System.Collections;
using System.Collections.Generic;
using Google.Apis.Sheets.v4;
using Google.Apis.Auth.OAuth2;
using System.IO;
using Google.Apis.Services;
using Newtonsoft.Json;
using WikipediaTests.Foundation_Class;
namespace AutomationProjects
{
[TestFixture]
public class TestClass : TestFoundation
{
public class SpreadSheetConnector
{
//Codeblock from guide pasted here!
}
[Test]
public void test1()
{
//Test case 1. Do XYZ...
}
}
}
In the code block included in the guide there is a section that reads the JSON credential file:
private void ConnectToGoogle()
{
GoogleCredential credential;
using (var stream = new FileStream(Path.Combine(HttpRuntime.BinDirectory, "Export Project-03e8aa07234e.json"),
FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream).CreateScoped(_scopes);
}
//...
But I get an error for the 'HttpRuntime' saying: Error CS0103 The name 'HttpRuntime' does not exist in the current context
There is no suggestion from VS to add a new 'using' reference so I'm assuming that is not the problem.
So what could be the problem? To whole codeblock from the: guide
Short answer - yes.
Long answer - I believe you need to add the System.Web dll here. C# projects do not add all dependencies by default -- rather, they provide you with a list of potential references, and let the user pick and choose on an as-needed basis.
Under your project, find the Dependencies section. Right click, and click Add Reference. Under Assemblies, find System.Web and check the box next to it, then click OK.
Once you add that, then you will need to add using System.Web to the top of your file.
This guide may help too: https://learn.microsoft.com/en-us/visualstudio/ide/how-to-add-or-remove-references-by-using-the-reference-manager?view=vs-2019

how can I load values from App.config in c# using .Net Framework 4 Client Profile

I'm having difficulty getting my settings out of App.config. The research I've done so far says that I should be able to use ConfigurationManager.AppSettings (which is part of System.Configuration).
However, I can't get it to compile. And of course it doesn't like the older method (ConfigurationSettings.AppSettings) either as its obsolete.
What have I missed here?
Is it my project's Target Framework (currently set to ".Net Framework 4 Client Profile
")?
And example of my code follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
namespace myNameSpace
{
class Program
{
private void LoadAppConfig()
{
string mySetting;
//This won't compile
mySetting =
System.Configuration.ConfigurationManager
.AppSettings["mySettingName"];
//This compiles but of course is obsolete, and I get that warning.
mySetting =
System.Configuration.ConfigurationSettings
.AppSettings["mySettingName"];
}
static void Main(string[] args)
{
// stuff happens
}
}
}
You need to add a reference to System.Configuration

ConfigurationManager return null instead of string values

I am trying to retrieve values from my App.config file which is stored in my working directory, however when I run the program it returns null. I am very confused why this is so, and have looked over the code many times in an attempt to spot an error.
Here is my App.config file code:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="provider" value="System.Data.SqlClient" />
</appSettings>
<connectionStrings>
<add name="connection" connectionString="Data Source=(local)\SQLEXPRESS;Initial Catalog=Autos;Integrated Security=True;Pooling=False" />
</connectionStrings>
</configuration>
Here is my C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.Common;
namespace DataProviderFun
{
class Program
{
static void Main(string[] args)
{
string p = ConfigurationManager.AppSettings["provider"];
string c = ConfigurationManager.ConnectionStrings["connection"].ConnectionString;
...
When I run this code, p = null and c = null.
I have referenced System.Configuration.dll.
Did you ensure that the config file is placed correctly at the directory from which you're running the application? Is there actually a file called <app name>.exe.config in that directory?
I'm just guessing here - maybe you added the App.Config file in a different project then your exe assembly project...?
By the way, I copied your code and App.Config as is to a clean project, and this code worked for me. So I'd look in the direction of the config file itself and not in the code. The code is fine...
Hope this helps,
Ran
If your config file use in different class library you must change your name YourClasslibraryDllname.dll.config and you must change config file copy to output directory property
Ex:
YourSolution
ClassLibrary_1
ClassLibrary_1.dll.config
ApplicationConfigurationReader.cs
ConfigurationConst.cs
ClassLibrary_2
ConsoleApp
Rename your config file like this YourClasslibraryDllname.dll.config
Open Properties Window
Change Do Not Copy to Copy Always
Add reference -> Assembly -> System.Configuration
Add below clases in ClassLibrary_1 Project
ConfigurationConst Class using System.Configuration;
public static class ConfigurationConst
{
public static KeyValueConfigurationCollection Configs;
}
ApplicationConfigurationReader class using System.Configuration;
internal class ApplicationConfigurationReader
{
public void Read()
{
// read assembly
var ExecAppPath = this.GetType().Assembly.Location;
// Get all app settings in config file
ConfigurationConst.Configs = ConfigurationManager.OpenExeConfiguration(ExecAppPath).AppSettings.Settings;
}
}
Read Config using ClassLibrary_1;
static void Main(string[] args)
{
new ApplicationConfigurationReader().Read();
var Configval = ConfigurationConst.Configs["provider"].Value;
Console.ReadKey();
}
i Hope you can get clean help
In Case all the settings are correct but still if you get null values, Please check your app.config file and replace the xml code as below,
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
</configuration>
Now Run your Code, you might see the proper values
If you have .dll in your debug folder, then rename your confif file to yourprojectname.dll.config. This worked in my case

Categories