Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

xunit constructor runs before each test

In a test class, the constructor starts before each test and the initialized data provided by the constructor isn't reachable by the following tests.

I'd like the initialized data to be accessible for all tests. (be created only once)

[Category("Basics")] [Collection("DD")] [ExcludeFromCodeCoverage] public class SecurityTests : TestUnitBase {     StartUpFixture fixture;     public AuthenticationTests(StartUpFixture fixture)        : base()     {         this.fixture = fixture;     }      [Fact(DisplayName = "Successful response Test1")]     public void SuccessfulResponseTest1()     {         var users = base.Db.Users.FirstOrDefault(x => x.Name == "abc");         ...     }      [Fact(DisplayName = "Successful response Test2")]     public void SuccessfulResponseTest2()     {         var users = base.Db.Users.FirstOrDefault(x => x.Name == "xyz");         ...     } 

Thanks in advance.

like image 229
M.Khooryani Avatar asked Oct 25 '17 07:10

M.Khooryani


People also ask

Does xUnit run constructor every test?

xUnit.net creates a new instance of the test class for every test that is run, so any code which is placed into the constructor of the test class will be run for every single test.

Do xUnit tests run in order?

Ordering classes and casesTests are executed in ascending order. If no Order attribute is specified default 0 is assigned. Multiple Order attributes can have same value.

Does xUnit run tests in parallel?

Running unit tests in parallel is a new feature in xUnit.net version 2. There are two essential motivations that drove us to not only enable parallelization, but also for it to be a feature that's enabled by default: As unit testing has become more prevalent, so too have the number of unit tests.

How do I ignore tests in xUnit?

xUnit.net does not require an attribute for a test class; it looks for all test methods in all public (exported) classes in the assembly. Set the Skip parameter on the [Fact] attribute to temporarily skip a test.


1 Answers

You can use Xunit Class fixtures. When using a class fixture, xUnit.net will ensure that the fixture instance will be created before any of the tests have run, and once all the tests have finished, it will clean up the fixture object by calling Dispose, if present. For example:

//similar to base class public class DatabaseFixture : IDisposable {     public SqlConnection Db { get; private set; }     public DatabaseFixture()     {         Db = new SqlConnection("MyConnectionString");          // initialize data in the test database     }      public void Dispose()     {         // clean up test data from the database     } }  //Class where you want to use shared class instance public class MyDatabaseTests : IClassFixture<DatabaseFixture> {     DatabaseFixture dbFixture;      public MyDatabaseTests(DatabaseFixture fixture)     {         this.dbFixture = fixture;     }      // write tests, using dbFixture.Db to get access to the SQL Server } 

For each test, it will create a new instance of MyDatabaseTests, and pass the shared instance of DatabaseFixture to the constructor.

Xunit Documentation here.

Hope it helps.

Edit 28/10 For multiple fixtures you can create a class which encapsulates the other two fixtures as below and create startup fixture to run before db fixture:

public class SecurityTestsFixture : IDisposable {     public DatabaseFixture Dbfixture { get; private set; }     public StartupTestFixture Startupfixture { get; private set; }      public SecurityTestsFixture()     {         Startupfixture = new StartupTestFixture();         Dbfixture = new DatabaseFixture(Startupfixture);     }      public void Dispose()     {         // clean up code         Dbfixture.Dispose();     }      public class StartupTestFixture     {         public string SqlConnString { get; private set; }         public StartupTestFixture()         {             SqlConnString = ConfigurationManager.AppSettings["SqlConnectionString"];              // other startup code         }     }      public class DatabaseFixture : IDisposable     {         public SqlConnection Db { get; private set; }         public DatabaseFixture(StartupTestFixture sFixture)         {             Db = new SqlConnection(sFixture.SqlConnString);              // initialize data in the test database         }          public void Dispose()         {             // clean up test data from the database         }     } } 

and test class:

public class Xunittests : IClassFixture<SecurityTestsFixture> {     SecurityTestsFixture _securityFixture;     public Xunittests(SecurityTestsFixture securityfixture)     {         _securityFixture = securityfixture;     }      [Fact(DisplayName = "Successful response Test1")]     public void SuccessfulResponseTest1()     {         var db = _securityFixture.Dbfixture.Db;         //var users = db.Users.FirstOrDefault(x => x.Name == "...");         Assert.Equal("test", "test");     } } 
like image 161
Shah Avatar answered Sep 18 '22 23:09

Shah