ConfigurationManager code fails when called from NUNIT project - c#

In my C# class project, I have a helper class which has the following property
public class Helper
{
public string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
}
}
}
My following test fails when I call the Helper class from NUNIT project with error message: Failure: System.NullReferenceException : Object reference not set to an instance of an object.
[Test]
public void connection_string_exists()
{
string connection = new Helper().ConnectionString;
Assert.NotNull(connection);
}
If I run the line of code new Helper().ConnectionString from a asp.net project then it works. Why does the Test fail?
Please let me know.

I suspect your Nunit tests are part of a different project and when you run the tests, ConfigurationManager looks at the config file of your test project and does not find "MyConnectionString"

Related

I added a reference to the main project, but the testing project still doesn't see the classes of main

My solution has a project that contains all the program logic.
I created a unit test project, added a reference to the main project, but still can't use classes from it to create tests.
My code:
namespace Program
{
public class Class
{
public Class()
{
///
}
public int foo()
{
///
}
}
}
My tests code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Program; // cs0246
namespace ProgramTests
{
[TestClass]
public class ClassTests
{
[TestMethod]
public void foo_()
{
// Arrange
Class testClass; // this code also have cs0246 error
// Act
// Assert
}
}
}
In this code, using Program; underlined in red with cs0246 error. But namespace ProgramTests have the reference to Program (there is a checkmark in the reference manager). How can i fix it?
Image of Solution Explorer
Please, check the framework version you are using. Maybe Tests library has framework which is no compatible with ClassLib Framework

Why the Xunit CollectionDefinition Not Working with Class Library in .NET 6 Web App?

When developing a web app, quite often we need to do unit testing against objects in class libraries. I run into the problem when trying to use Xunit "CollectionDefinition" feature to share content between multiple test cases. (see details in following sections)
TEST ENVIRONMENT
Windows 11 and Visula Studio 2022 community edition
.NET 6 Web App "XunitDemo" with a .NET 6 Class Library "DataHelper"
Packages:
Xunit 2.4.2
Xunit.runner.visualstudio 2.4.3
PROBLEM DESCRIPTION:
In order to test sharing content between following test cases, I wrote test code with following components
The class to be tested: DataHelper.TextHelper (see code segment 1)
Test project: DataHelperTests
In test project, created the "fixture" object TextHelperFixture (see code segment 2)
In test project, Created the xunit CollectionDefinition (see code segment 3)
To make sure the TextHelperFixture works correctly, I setup first test case: TextHelperFixtureTest (see code segment 4)
To test the content sharing between multiple test cases, I setup 2 separate test cases: CollectionDefTest1 & CollectionDefTest2 with [Collection(....)] attribute. Each has 1 test method (see code segments 5 and 6)
Testing Steps:
To verify the "fixture" object actually works, I run TextHelperFixtureTest and it passed with no error.
To test the "CollectionDefinition", I tried to execute first test method: CollectDefTest1.CollDefTest1. It failed with following error:
 DataHelperTests.CollectionDefTest1.CollDefTest1
Source: CollectionDefTest1.cs line 15
Duration:1 ms
Message: The following constructor parameters did not have matching fixture data: TextHelperFixture fixture
When running second test with CollectionDefTest2.CollDefTest2, the similar error occurred:
 DataHelperTests.CollectionDefTest2.CollDefTest1
Source: CollectionDefTest2.cs line 16
Duration: 1 ms
Message: The following constructor parameters did not have matching fixture data: TextHelperFixture thFixture
QUESTIONS
The test result of "TextHelperFixtureTest" showed that the "Fixture" object is working fine when it was directly instantiated inside of the test case. Why using the "CollectionDefinition" caused the error of unable to find the "Fixture" class?
I thought that it was possible the CollectionDefinition won't work with class library. I actually setup a console app with class library, The "CollectionDefinition" was working fine there. Why this problem occurs when the main project is a .NET 6 web app?
It will be greatly appreciated if anyone has suggestions and troubleshooting tips.
TEST CODE SEGMENTS
------ Code Segment 1: Class in library to be Tested ------
namespace DataHelper
{
public class TextHelper
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public TextHelper() { }
public TextHelper (string fn, string ln)
{
FirstName = fn;
LastName = ln;
}
public string GetFullName()
{
return $"{FirstName} {LastName}";
}
}
}
------ Code Segment 2: "Fixture" object in test project ------
using System;
namespace DataHelperTests
{
public class TextHelperFixture: IDisposable
{
public string FullName { get; private set; }
public TextHelperFixture()
{
TextHelper st = new TextHelper("Jason", "Williams");
FullName = st.GetFullName();
}
public void Dispose()
{
}
}
}
------ Code Segment 3: CollectionDefinition in Test project ------
using Xunit;
namespace DataHelperTests
{
[Collection("TextHelper Collection")]
public class TextHelperFixtureCollection : ICollectionFixture<TextHelperFixture> { }
}
------ Code Segment 4: Test case to verify "fixture" object ------
using Xunit;
namespace DataHelperTests
{
public class TextHelperFixtureTest
{
private TextHelperFixture _fxt;
public TextHelperFixtureTest()
{
_fxt = new TextHelperFixture();
}
[Fact]
public void FixtureTest()
{
Assert.NotNull(_fxt.FullName);
}
}
}
------ Code Segment 5: first test utilizes the Collection ------
using Xunit;
namespace DataHelperTests
{
[Collection("TextHelper Collection")]
public class CollectionDefTest1
{
private TextHelperFixture _fixture;
public CollectionDefTest1(TextHelperFixture fixture)
{
_fixture = fixture;
}
[Fact]
public void CollDefTest1()
{
string result = _fixture.FullName;
Assert.Contains("Jason", result);
}
}
}
------ Code Segment 6: second test case that ultilizes the collection ------
using Xunit;
namespace DataHelperTests
{
[Collection("TextHelper Collection")]
public class CollectionDefTest2
{
private TextHelperFixture _fixture;
public CollectionDefTest2(TextHelperFixture thFixture)
{
_fixture = thFixture;
}
[Fact]
public void CollDefTest1()
{
Assert.NotNull(_fixture.FullName);
}
}
}
You've done 99% of it perfectly (it's a pleasure to answer a question where someone has clearly taken the time to surface as much as possible in textbook fashion like here) - just a typo/mistake under
Code Segment 3: CollectionDefinition in Test project
you are using the [Collection] attribute as one correctly would on the Test Class, but you meant [CollectionDefinition], which is the counterpart for the definition bit...
(Putting this in long form for future readers - you obviously had it all sorted but just typo'd in this instance)

How do I add a DbContext to an MSTest project?

I trying to test some code that uses Entity Framework, but I can't figure out how to reference the EF Context classes from the separate MSTest project. Both projects are in the same solution.
Cannot convert lambda expression to type 'DbContextOptions' because it is not a delegate type
In my Test case:
[TestClass]
public class GreenCardUserTest
{
[TestMethod]
public void TestAddUser()
{
// REFERENCE TO OTHER PROJECT. WORKS FINE
AppUserViewModel a = new AppUserViewModel();
//LIKELY INCORRECT attempt to duplicate code from Startup.cs in other project
using (GreenCardContext _gc = new GreenCardContext(options => options.UseSqlServer(Configuration.GetConnectionString("MyConnection"))))
{
new GCLandingUserModel().AddUser(a,_gc);
}
}
}
Excerpt from main project Startup.cs (which works fine):
services.AddDbContext<GreenCardContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyConnection")));
I would suggest using InMemoryDatabase. In your test class, use [TestInitialize] to setup your dummy database:
[TestClass]
public class GreenCardUserTest
{
private readonly context;
[TestInitialize]
public Setup()
{
DbContextOptions<GreenCardContext> options;
var builder = new DbContextOptionsBuilder<GreenCardContext>();
builder.UseInMemoryDatabase();
var options = builder.Options;
context = new GreenCardContext(options);
}
[TestMethod]
public void TestAddUser()
{
// user context here...
}
}
What you have to do is:
1) Add a reference in your test project to your context's project (if you haven't already)
2) Add references to Entity Framework to your test project
3) Add an appconfig to your test project and set entity framework config on it. Your test will read the configuration from it's own config, not your app's. Very useful as you can, by example, use dblocal and codefirst in tests and sqlserver when on running :)
You have done some of this, I think the point you are missing is the third :)
The code that you have from Startup.cs is using a delegate to tell your application how to build your DbContext at runtime.
However in your test, you need to actually provide an instance of DbContextOptions, not just a delegate. To do this, you can use DbContextOptionsBuilder:
var options = new DbContextOptionsBuilder<GreenCardContext>()
.UseSqlServer(Configuration.GetConnectionString("MyConnection"))
.Options;
using (GreenCardContext _gc = new GreenCardContext(options))
{
new GCLandingUserModel().AddUser(a,_gc);
}
Also, if you do insist on unit testing your DbConext, you may want to look into using InMemoryDatabase so that you don't need an open SQL connection in your tests. See this document for more details.

In a Visual Studio package, can I simulate (DTE) GetService(typeof (DTE)) for tests?

In my package I am using (DTE) GetService(typeof (DTE)) to get information about the currently opened solution. Is there a way to simulate this for a test, particularly so that I can build using dte.Solution.SolutionBuild?
Code in main package class:
var solutionModel = new SolutionModel(((DTE) GetService(typeof (DTE))).Solution);
SolutionModel class (stripped back):
public class SolutionModel
{
private readonly Solution _packageSolution;
public SolutionModel(Solution solution)
{
_packageSolution = solution;
}
public SolutionModel() {} // This constructor is used for tests so _packageSolution will be null
public bool Build()
{
if (_packageSolution != null)
{
var buildObject = _packageSolution.SolutionBuild;
buildObject.Build(true);
return buildObject.LastBuildInfo == 0;
}
return ManualCleanAndBuild(); // current messy alternative way of doing the build for tests
}
}
So I want to be able to use the _packageSolution build rather than ManualCleanAndBuild() in my tests.
Assuming that you are referring to integration tests (and not to unit tests) where you need to load your package in a real Visual Studio instance, it depends on the testing framework that you are using. If you are using MSTest with the VSIDE Host Adapter (the integration test project that the package wizard creates if you mark the checkbox in the last page of the wizard) there is a Utils.cs file that uses the static VsIdeTestHostContext class to get the DTE instance or services:
public static class VsIdeTestHostContext
{
[CLSCompliant(false)]
public static DTE Dte { get; }
public static IServiceProvider ServiceProvider { get; set; }
}
If you want to learn the inners of the VS IDE Host Adapter I think that the VS 2008 SDK was the last SDK that provided the source code and the documentation (http://msdn.microsoft.com/en-us/library/bb286982%28v=vs.90%29.aspx)
The way I ended up 'solving' this was to mock EnvDTE.Solution instead (seems like it can only be done in the Package_IntegrationTests project which is created for you - you can't reference EnvDTE in any other project). I couldn't figure out how to use the methods in Utils.cs as suggested by Carlos below to open my existing solutions.

Running TestFixtures from multiple class files in NUnit

I have a simple NUnit project in C#. I have a file TestFixture.cs that successfully runs its four tests. If I want to add additional tests in a new CS file, how do I do this? If I simply copy the code from TestFixture.cs into a new TestFixture2.cs and rename the TestFixture classes to TestFixture3 and 4 respectively, they do not execute. I would think they would automatically run. Do I need to tell the runner specifically if it is a file other than TestFixture.cs? Here is my code:
namespace NUnitTest1
{
[TestFixture]
public class TestFixture3
{
[Test]
public void TestTrue()
{
Assert.IsTrue(true);
}
// This test fail for example, replace result or delete this test to see all tests pass
[Test]
public void TestFault()
{
Assert.IsTrue(true);
}
}
[TestFixture]
public class TestFixture4
{
[Test]
public void TestTrue()
{
Assert.IsTrue(true);
}
// This test fail for example, replace result or delete this test to see all tests pass
[Test]
public void TestFault()
{
Assert.IsTrue(true);
}
}
}
My unit test runs by executing a command line program using the following code:
namespace NUnitTest1
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string[] my_args = { Assembly.GetExecutingAssembly().Location };
int returnCode = NUnit.ConsoleRunner.Runner.Main(my_args);
if (returnCode != 0)
Console.Beep();
}
}
}
NUnit will automatically get all types marked with TestFixture attribute from test assembly when you load it (it does not matter whether fixtures in one .cs file or in separate). Then NUnit will search for methods marked with Test or TestCase attributes and load them. If NUnit don't see some test, then make sure you loaded latest version of your test assembly.
NOTE: If you are using NUnit test runner, then there is nice setting Reload when test assembly changes. With this option turned on NUnit will automatically reload test assembly when you rebuild it in Visual Studio.

Categories