I am moving and refactoring a code from .NET-Framework to .NET-Core in C#. When I run a simple test on a method which is supposed to sort a List, I get this error:
"System.MissingMethodException: Method not found: 'System.Collections.IDictionary Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.get_Properties()'."
I have checked references to other namespaces that are necessary. I searched for the error online and I realized that the TestContext Class has not been provided in .NET Core yet! Is there another way or a replacement library I can use instead? Thank you.
[TestMethod]
public void TestMethod()
{
// Arrange
// Grab an arbitrary start time.
Time startTime = Time.Now;
List<TimeValue> values = new List<TimeValue>
{
// Make sure that second timestamp comes before the first
timestamp
new TimeValue(startTime.PlusMinutes(1)),
new TimeValue(startTime)
};
// Ensure that this is sorted in ascending order of time.
List<TimeValue> expectedValues = values.OrderBy(value =>
value.Timestamp).ToList();
CollectionAssert.AreNotEqual(expectedValues, values);
// Act
SortArray myObj = new SortArray(values);
// Assert
CollectionAssert.AreEqual(expectedValues, SortArray.Values);
}
I expect the TestMethod to run, but it does not run and gives me the following error:
'System.Collections.IDictionary Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.get_Properties()'.
A possible alternate you could use is xUnit. Its a open sourced tool and you can use it with .NET Core.
Microsoft offers a tutorial on how to xUnit with the .NET Core.
Another possibility is "dotnet test" which is a unit testing tool that Microsoft made compatible for .NET Core.
Try adding to your test class the following property:
public TestContext TestContext { get; set; }
In general, MSTest does not seem to be actively developed. As it's shipped with Visual Studio, Microsoft keeps it working on .NET (and somewhat even on .NET Core) but they seem to use xUnit themselves internally, so it makes sense to consider switching your tests to xUnit either.
It works when you provide a field of type TestContext. It doesn't work when you make it a property. Following works with .NET Core 3.1 as described here.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace TimeLogger.Tests
{
[TestClass]
public class YourTestClass
{
private static TestContext Context;
[ClassInitialize]
public static void InitClass(TestContext testContext)
{
Context = testContext;
}
[TestMethod]
public void Test_1()
{
Assert.IsTrue(true);
}
[TestMethod]
public void Test_2()
{
Assert.IsTrue(true);
}
}
}
But after changing
private static TestContext Context;
into
private static TestContext Context { get; set; }
causes tests don't run anymore.
Related
All,
I am using Unit test framework to write my tests in .net. I wrote some unit tests that all access a configuration object (via AppConfig.Current) that is internally a class static.
In the startup I initialize this configuration object and use it immediately in the following line like this:
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
var appCfg = AppConfig.Current;
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "conf/app.settings.xml");
appCfg.Load(path);
var _ = AccountingContext.Current; // <= AccountingContext references the configuration object via "AppConfig.Current" to read some configuration values and initialize the accounting context but I receive a different instance (ONLY in release mode) ....
}
After loading configuration, next line uses this configuration object (AccountingContext.Current) to initialize itself from the configuration object.
The issue is, the tests run fine in Debug mode but in Release mode when I reference the configuration object I get a different object (I know this for a fact because the configuration is not loaded).
So what is the deal with using static reference in unit tests in release mode???
UPDATE: SELF ANSWERED
The issued lied in the "AccountingContext" class.
This class is also a static and it initialized itself like this:
public static AccountingContext Current { get; set; } = new AccountingContext();
public AccountingContext()
{
CompanyAccessContext = _CreateCompanyAccessContext();
}
Changing this intialization to using a static ctor resolved this issue and now everything works:
public static AccountingContext Current { get; set; }
static AccountingContext()
{
Current = new AccountingContext();
}
public AccountingContext()
{
CompanyAccessContext = _CreateCompanyAccessContext();
}
Looks like optimizations were made which changed the actual flow of initialization of AccountingContext. That's a bit unwanted, not sure if this is what everyone expects.
I also found this good resource:
Static member variable not being initialized in Release - Compiler/clr bug?
Cause of this issue was not using static ctor which guarantees order of initialization. For more details, see updated comments above.
I am using the xUnit.net test framework and in each unit test I have certain steps which I am doing in each case. I would like to know if there is a way I call this method once before my unit case starts and also call when all unit test cases has been executed.
For example: In the scenario below I have two unit cases and in each case I am creating a local DB, populating it with data and then running my test and once it is done I am calling method to delete the DB. This I am doing in each test case. Instead of multiple creation I would like to create once and populate once and then delete db once all test case has been executed. It is important for me to delete what I have created as the test cases has certain cases which will fail if Database is not created when the tests are executed.
[Fact]
public void UnitCase1()
{
CreateDb();
UploadData();
...//My set of operation to test this case
...//Assert
DeleteDb()
}
[Fact]
public void UnitCase2()
{
CreateDb();
UploadData();
...//My set of operation to test this case
...//Assert
DeleteDb()
}
Editing after Answer from Eric:(I tried but its not working)
public class CosmosDataFixture : IDisposable
{
public static readonly string CosmosEndpoint = "https://localhost:8081";
public static readonly string EmulatorKey = "Mykey";
public static readonly string DatabaseId = "Databasename";
public static readonly string RecordingCollection = "collectionName";
string Root = Directory.GetParent( Directory.GetCurrentDirectory() ).Parent.Parent.FullName;
DocumentClient client = null;
public void ReadAllData( DocumentClient client )
{
//reading document code
}
public void ReadConfigAsync()
{
client = new DocumentClient( new Uri( CosmosEndpoint ), EmulatorKey,
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp
} );
}
public void CreateDatabase()
{// create db code
}
private void DeleteDatabase()
{
// delete db code
}
public CosmosDataFixture()
{
ReadConfigAsync();
CreateDatabase();
ReadAllData( client );
}
public void Dispose()
{
DeleteDatabase();
}
}
public class CosmosDataTests : IClassFixture<CosmosDataFixture>
{
CosmosDataFixture fixture;
public CosmosDataTests( CosmosDataFixture fixture )
{
this.fixture = fixture;
}
[Fact]
public async Task CheckDatabaseandCollectionCreation()
{
List<string> collectionName = new List<string>();
var uri = UriFactory.CreateDatabaseUri(DatabaseId);// don't get DatabaseId or client says does not exist in current context
var collections = await client.ReadDocumentCollectionFeedAsync( uri );
foreach( var collection in collections )
{
collectionName.Add( collection.Id);
}
}
That's what [SetUp] and [TearDown] are for in NUnit. They are run right before and right after each test case, respectively. In xUnit you would usually implement a default constructor and IDisposable.
For example:
public TestClass()
{
CreateDb();
UploadData();
}
public void Dispose()
{
DeleteDb()
}
[Fact]
public void UnitCase1()
{
...//My set of operation to test this case
...//Assert
}
[Fact]
public void UnitCase2()
{
...//My set of operation to test this case
...//Assert
}
As other people have pointed out, such tests are in mainstream parlance not unit tests, but rather integration tests. xUnit.net is a fine framework for those kinds of tests, though, so apart from the semantic distinction, it makes little technical difference.
Apart from setting up the database in the test class' constructor and tearing it down in Dispose, as outlined by Eric Schaefer, you can also use xUnit.net's BeforeAfterTestAttribute. You'll then override Before to set up the database, and override After to tear it down:
public class UseDatabaseAttribute : BeforeAfterTestAttribute
{
public override void Before(MethodInfo methodUnderTest)
{
CreateDb();
UploadData();
base.Before(methodUnderTest);
}
public override void After(MethodInfo methodUnderTest)
{
base.After(methodUnderTest);
DeleteDb();
}
}
You can then annotate either each test method, or the entire test class with the attribute. I usually just annotate the class:
[UseDatabase]
public class DbTests
{
// Tests go here...
}
Since tests that use a database interact with a shared resource (the database), they can't easily run in parallel. By default, xUnit.net runs tests in parallel, so you may want to disable that. You can do it by adding an xunit.runner.json file:
{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"parallelizeTestCollections": false
}
Finally, at least if you're using SQL Server, connection pooling will prevent you from deleting the database. You can either turn off connection pooling for your tests, or forcibly close other connections before teardown.
In my experience in Testing, I see 2 points here:
1-If you are checking that the data from the DB to another point in the program is being transmited correctly, that is Integration Testing, and it should be out of scope in the Unit Testing Plan, make sure that the responsabilities of a Unit Tester are clear where you work as there are some companies which avoid Integration Testing levels by assuming that if Functional Testing is 'OK', integrations should be too.
2- You mention at the end
It is important for me to delete what I have created as the test cases has certain cases which will fail if Database is not created when the tests are executed
but
I would like to create once and populate once and then delete db once all test case has been executed.
If I understand correctly, you need to do it for each Test Case as not all test cases are checking the same scenario, so it looks like those statements are the real problem here.
To answer your question, as it seems like you want to automate the process with minimum maintenance for the next releases, and I also know how the work environment tend to corner you to do some stuff that shouldn't be, I could think of a Preconditions Function and a Postcondition one, where you do it once and that's it.
If that is not possible for whatever reason, try to create another Test Case at the beginning (like Test Case 0) where you create and populate the DB (if apply, or separate it if needed) and another one at the end where you delete it.
I'm not familiar with the framework you are using, but I have a lot of experience in Testing, opening test levels and automating tasks, and hope that my answer could be of some help.
I'm trying to write Unit Tests in C# .Net Core 2.1 Function App with xUnit framework for something like this, where the class variables are initialized through Autofac dependency injection.
public class TestClass
{
private readonly ISampleLogger<SampleReporting> sampleLogger;
private readonly IRequestSender requestSender;
public SampleReporting(IDependencyResolver dependencyResolver)
{
dependencyResolver?.Resolve<ISampleLoggingStartup>().Configure();
this.sampleLogger = dependencyResolver.Resolve<ISampleLogger<SampleReporting>>();
this.requestSender = dependencyResolver.Resolve<IRequestSender>();
}
...
public void FunctionToTest(string s)
{
...
I'm trying to mock the dependencyresolver object but couldn't figure out how to mock the variables sampleLogger and requestSender as they are getting set internally in the constructor. Any leads will be appreciated.
I tried to mock IDependencyResolver like this, but could not get it to work:
private readonly Mock<IDependencyResolver> dependencyResolverMock;
[Fact]
public void Test1()
{
dependencyResolverMock.Setup(x => x.Resolve<It.IsAny<ISampleLoggingStartup>>().Configure());
Having this in the test constructor worked fine for me:
public ReportingTest()
{
dependencyResolverMock = new Mock<IDependencyResolver>();
dependencyResolverMock.Setup(x => x.Resolve<ISampleLogger<SampleReporting>>()).Returns(Mock.Of<ISampleLogger<SampleReporting>>());
dependencyResolverMock.Setup(x => x.Resolve<IRequestSender()).Returns(Mock.Of<IRequestSender>());
}
I'm having this issue that can't resolve, I'm upgrading from NUnit 2.6.4 to 3.9.0, my test project have multiple test class, and when I change NUnit version, some of my tests weren't discovered by test explorer, after some research, all tests missing inherits or somehow implement NHibernate and Spring NUnit testing nuget package. When I remove inheritance, tests are discover. No solution works for this.
Nuget packages version:
Spring.Testing.NUnit
2.0.1 NUnit 3.9.0
NHibernate 3.3.3.4
NUnitTestAdapter 3.9
This is my NHibernate class:
using System;
using NHibernate;
using Spring.Data.NHibernate.Generic;
using Spring.Data.NHibernate.Support;
using Spring.Testing.NUnit;
namespace Testproject{
public class NHibernateTestClass : AbstractTransactionalSpringContextTests
{
//Some methods here
}
}
This is my test class:
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace Testproject{
public class TestClass: NhibernateTestClass{
//Some test methods here
}
}
I have tried referencing NUnit framework in my NHibernateTestClass but, with no result.
Edit:
Forgot to add that my Hibernate test class was inheriting from that spring test class.
Just install NUnit3TestAdapter via nuget.
And add NUnit attributes([TestFixture],[Test]) before class and method declaring.
Well i have simmilar problem but with visual studio 2015 (community)
I have 2 test classes one is:
namespace WarehouseTemplate.Tests
{
[TestFixture]
public class Test1
{
[SetUp]
public void Init()
{
}
[Test()]
public void Can_generate_schema()
{
var cfg = new Configuration();
cfg.Configure();
new SchemaExport(cfg).Execute(true, true, false);
}
}
}
With can be found in test explorer, and then i have this one
namespace WarehouseTemplate.Tests
{
[TestFixture]
public class TestDao : AbstractDaoIntegrationTests
{
private IProductDao productDao;
private ISessionFactory sessionFactory;
// These properties will be injected based on type
public IProductDao ProductDao
{
set { productDao = value; }
}
public ISessionFactory SessionFactory
{
set { sessionFactory = value; }
}
[SetUp]
public void Init()
{
}
[Test()]
public void CustomerDaoTests()
{//logic here
}
}
}
where AbstractDaoIntegrationTests looks
namespace WarehouseTemplate.Tests
{
[TestFixture]
public class AbstractDaoIntegrationTests : AbstractTransactionalDbProviderSpringContextTests
{
protected override string[] ConfigLocations
{
get
{
return new string[]
{
"referenceString"
};
}
}
}
}
But i cant find this test only first one:
NUnit Adapter 3.9.0.0: Test execution started
Running all tests in E:\Zabava\C# programy\WarehouseTemplate\WarehouseTemplate\bin\Debug\WarehouseTemplate.exe
NUnit3TestExecutor converted 1 of 1 NUnit test cases
NUnit Adapter 3.9.0.0: Test execution complete
So far any tip for possible problem is that spring NET has different NUNIT version which needs scpeficy reference or NUnit Adapter
I found Answer and solution
I just instale NUnit 2.6.3 )i manually choose older one, and propriet Adapter version now i can see my tests
I'm trying to test business logic in queries in services. So I don't want my tests to have real access to the database, because they are unit tests, not integration tests.
So I've made a simple example of my context and how I'm trying to shim it.
I have an entity
public class SomeEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
and a service
public class Service
{
public int CountSomeEntites()
{
using (var ctx = new Realcontext())
{
int result = ctx.SomeEntities.Count();
return result;
}
}
}
And this is the real context
public partial class Realcontext : DbContext
{
public virtual DbSet<SomeEntity> SomeEntities { get; set; }
public Realcontext() : base("name=Realcontext")
{
InitializeContext();
}
partial void InitializeContext();
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}
So I've tried to create a fake context and I detourned the constructor of the real context in my test method
This is the fake context
public class FakeContext : DbContext
{
public DbSet<SomeEntity> SomeEntities { get; set; }
public FakeContext()
{
}
}
And finally the test class
[TestClass]
public class ServiceTests
{
[TestMethod]
public void CountEmployee_ShoulReturnCorrectResult()
{
using (ShimsContext.Create())
{
ShimRealcontext.Constructor = context => GenerateFakeContext();
ShimDbContext.AllInstances.Dispose = () => DummyDispose();
Service service = new Service();
int result = service.CountSomeEntites();
Assert.AreEqual(result, 2);
}
}
private FakeContext GenerateFakeContext()
{
FakeContext fakeContext = new FakeContext();
fakeContext.SomeEntities.AddRange(new[]
{
new SomeEntity {Id = 1, Name = "entity1"},
new SomeEntity {Id = 2, Name = "entity2"}
});
return fakeContext;
}
}
When I run the test, the RealContext constructor is returned properly, a FakeContext is built in the GenerateFakeContext() method, it contains 2 SomeEntities and it is returned, but right after, in the service, the property SomeEntities of the variable ctx equals to null.
Is it because my variable ctx is declared as a new RealContext()? But calling the constructor of RealContext returns a FakeContext(), so isn't the variable supposed to be of type FakeContext?
Am I doing something wrong? Or is there any other way to test the service without accessing the real database?
I had the simlair situation and I solved it with build configuration and conditional compilation. It's not the best solution, but it worked for me and solved the problem. Here is the receipt:
1. Create DataContext interface
First you need to create an interface which will be implemented by both context classe you going to use. Let it be named just 'IMyDataContext'. Inside it you need to describe all DbSets you need to have access to.
public interaface IMyDataContext
{
DbSet<SomeEntity> SomeEntities { get; set; }
}
And both your context classes need to impelemt it:
public partial class RealDataContext : DataContext, IMyDataContext
{
DbSet<SomeEntity> SomeEntities { get; set; }
/* Contructor, Initialization code, etc... */
}
public class FakeDataContext : DataContext, IMyDataContext
{
DbSet<SomeEntity> SomeEntities { get; set; }
/* Mocking, test doubles, etc... */
}
By the way you can even make properies read-only at interface level.
2. Add 'Test' build configuration
Here you can find how to add new build configuration. I named my configuratin 'Test'. After new configuration is created, go to your DAL project properties, Build section on the left pane. In the 'Configuration' drop-down select the configuration you've just created and in input 'Conditional compilation symbols' type 'TEST'.
3. Incapsulate context injection
To be clear, my approach is still method/property based DI solution =)
So now we need to implement some injection code. For simplicity you can add it right into your service or extract into another class if you need more abstraction. The main idea is to use conditional compilation direcitves instead of IoC framework.
public class Service
{
// Injector method
private IMyDataContext GetContext() {
// Here is the main code
#if TEST // <-- In 'Test' configuration
// we will use fake context
return new FakeDataContext();
#else
// in any other case
// we will use real context
return new RealDataContext();
#endif
}
public int CountSomeEntites()
{
// the service works with interface and does know nothing
// about the implementation
using (IMyDataContext ctx = GetContext())
{
int result = ctx.SomeEntities.Count();
return result;
}
}
}
Limitations
The described approach solves the the problem you described, but it has a limitation: as IoC allows you switch contexts dynamically at runtime, conditional complation requires you to recompile the solution.
In my case it's not a problem - my code isn't covered by tests for 100% and I don't run them on each build. Usually I run tests only before commiting the code, so it's very easy to switch the build configuration in VS, run tests, make sure that nothing was broke and then return to debug mode. In release mode you don't need to run test either. Even if you need - you can craete "Release build test mode" configuration and continue to use the same solution.
Another problem is if you have continuos integration - you need to make additional setup to your build server. Here you have two ways:
Setup two build definitions: one for release and one for tests. If your server is setup to automatic release you need to be careful because test fails will be shown in the second one while the first is deployed.
Set complex build definition which builds your code in Test configuration for the first time, runs test and if they are OK - then recompiles the code in target configuration and prepare to deploy.
Thus, as any solution this one is yet another compromise between simplisity and flexibility.
UPDATE
After some time I understand that the way I described above is very heavy. I mean - build configurations. In case of only two IDataContext implementations: 'Core' and 'Fake' you can simply use bool paramenter and simple if/else branches instead of compilation directives #if/#else/#endif and all the head ache configuring your build server.
If you have more than two implementations - you can use enum and switch block. A probem here is to define what you will return in default case or if value is out of enum's range.
But the main benefit of such approach is that you can be no longer bound to compilation time. Injector parameter could be changed at any time, for example using web.config and ConfigurationManager. Using it you could event switch your data context at run time.