Introduction
With the help of xUnit's class fixtures, we can easily distribute setup and teardown code among all test methods in a test class. This feature ensures a uniform and effective testing environment for the whole suite of tests by improving code readability and maintainability, as well as encouraging consistency in the initialization and cleanup procedures.
We can encapsulate this shared initialization logic by using a fixture class instead of duplicating the same setup logic in every single test method. By doing this, we encourage standardized and structured testing methods in addition to streamlined code by establishing a sense of consistency and coherence throughout the entire test suite. This improves our code maintainability and creates a testing environment that works well together by managing common setup procedures and applying them consistently across the entire test suite.
In my previous article, you will see that I manually created the object and used it in the unit test method.
If you haven't looked at that article, then please refer to this.
Let's try to register that dependency in the class fixture and use those dependencies in the test class.
We will resolve that dependency on the test class constructor and use it in the unit test method.
Creating a Class Fixture
public class TestClassFixture
{
public IServiceProvider ServiceProvider;
private readonly IConfiguration _configuration;
public TestClassFixture()
{
var services = new ServiceCollection();
_configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.AddJsonFile("TestData/empdata.json", optional: false, reloadOnChange: false)
.AddEnvironmentVariables()
.Build();
services.AddSingleton(_configuration);
services.AddScoped(typeof(Mock<IEmpRepository>), typeof(Mock<IEmpRepository>));
ServiceProvider = services.BuildServiceProvider();
}
}
Use Fixture in the Test Class
public class EmpControllerTest : IClassFixture<TestClassFixture>
{
private readonly EmpController _empController;
private readonly Mock<IEmpRepository> _empRepository;
private readonly IConfiguration _configuration;
public EmpControllerTest(TestClassFixture testClassFixture)
{
_empRepository = testClassFixture.ServiceProvider.GetRequiredService<Mock<IEmpRepository>>();
_empController = new EmpController(_empRepository.Object);
_configuration = testClassFixture.ServiceProvider.GetRequiredService<IConfiguration>();
}
}
Let’s run the test class and check if the fixture class works as we define it or not.
See the screenshot below as we execute our newly created fixture class and register dependencies on the ServiceProvider property.
![ServiceProvider]()
![Config]()
In the test class constructor, we are able to see those dependencies and resolve them for use in the test class method.
![Class constructor]()
I can see that our test method will be executed successfully.
![Test method]()
You can see the screenshot below for every unit test case that has been executed successfully.
![Unit test case]()
Summary
Utilizing Class Fixtures to their fullest, we've found a happy medium between maintaining stability and completing tasks quickly. This has made it possible for our.NET projects to have more robust and flexible unit tests.
We learned the new technique and evolved together.
Happy coding!