Introduction
Testing is a crucial part of modern software development. As applications grow in complexity, ensuring that code behaves as expected becomes increasingly important. In the .NET ecosystem, xUnit is one of the most popular unit testing frameworks used by developers to write and execute automated tests.
What is xUnit?
xUnit.net is a free, open-source unit testing framework for .NET applications. It is the successor to NUnit and follows the xUnit testing architecture used across many programming languages.
xUnit helps developers:
- Verify application behavior
- Detect bugs early
- Prevent regressions
- Improve code quality
- Support continuous integration pipelines
Why Use xUnit?
Some benefits of using xUnit include:
1. Simplicity
xUnit provides a clean and straightforward syntax for writing tests.
2. Strong Community Support
It is widely adopted across the .NET ecosystem.
3. Built-in Dependency Injection Support
xUnit offers better support for modern development practices.
4. Parallel Test Execution
Tests can run in parallel, improving execution speed.
5. Cross-Platform Compatibility
Works on Windows, Linux, and macOS.
Prerequisites
Before getting started, ensure you have:
- .NET SDK installed
- Visual Studio, Visual Studio Code, or Rider
- Basic knowledge of C#
Verify your installation:
dotnet --version
Step 1: Create a .NET Solution
Create a new solution:
dotnet new sln -n CalculatorSolution
Navigate into the solution directory:
cd CalculatorSolution
Step 2: Create a Class Library Project
Create the application project:
dotnet new classlib -n CalculatorApp
Add it to the solution:
dotnet sln add CalculatorApp/CalculatorApp.csproj
Step 3: Create an xUnit Test Project
Create the test project:
dotnet new xunit -n CalculatorApp.Tests
Add the test project to the solution:
dotnet sln add CalculatorApp.Tests/CalculatorApp.Tests.csproj
Step 4: Add Project Reference
The test project must reference the application project.
Run:
dotnet add CalculatorApp.Tests reference CalculatorApp
Your solution structure should look like:
CalculatorSolution
│
├── CalculatorApp
│ └── Calculator.cs
│
└── CalculatorApp.Tests
└── CalculatorTests.cs
Step 5: Create a Simple Calculator Class
Inside the CalculatorApp project, create:
namespace CalculatorApp;
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Subtract(int a, int b)
{
return a - b;
}
}
Step 6: Write Your First xUnit Test
Create a test class:
using CalculatorApp;
using Xunit;
namespace CalculatorApp.Tests;
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calculator = new Calculator();
// Act
var result = calculator.Add(5, 3);
// Assert
Assert.Equal(8, result);
}
}
Understanding the Test Structure
A typical unit test follows the AAA pattern:
Arrange
Prepare required objects and data.
var calculator = new Calculator();
Act
Execute the method being tested.
var result = calculator.Add(5, 3);
Assert
Verify the expected outcome.
Assert.Equal(8, result);
Step 7: Run the Tests
Execute:
dotnet test
Expected output:
Passed! 1 test passed.
Step 8: Using Fact and Theory
xUnit provides two commonly used attributes:
Fact
Used when a test has no parameters.
[Fact]
public void Subtract_ReturnsCorrectResult()
{
var calculator = new Calculator();
var result = calculator.Subtract(10, 4);
Assert.Equal(6, result);
}
Theory
Used for data-driven tests.
[Theory]
[InlineData(2, 3, 5)]
[InlineData(10, 5, 15)]
[InlineData(7, 8, 15)]
public void Add_ReturnsExpectedResult(
int a,
int b,
int expected)
{
var calculator = new Calculator();
var result = calculator.Add(a, b);
Assert.Equal(expected, result);
}
This test runs three times using different inputs.
Common Assertions in xUnit
Equal
Assert.Equal(10, result);
NotEqual
Assert.NotEqual(5, result);
True
Assert.True(isValid);
False
Assert.False(isValid);
Null
Assert.Null(value);
NotNull
Assert.NotNull(value);
Contains
Assert.Contains("admin", roles);
Testing Exceptions
You can verify that a method throws an exception.
Example:
[Fact]
public void Divide_ByZero_ThrowsException()
{
var calculator = new Calculator();
Assert.Throws<DivideByZeroException>(
() => calculator.Divide(10, 0));
}
Using Test Fixtures
When multiple tests require shared setup, use fixtures.
Example:
public class DatabaseFixture
{
public string ConnectionString =>
"Server=localhost;";
}
public class DatabaseTests :
IClassFixture<DatabaseFixture>
{
private readonly DatabaseFixture _fixture;
public DatabaseTests(DatabaseFixture fixture)
{
_fixture = fixture;
}
[Fact]
public void TestConnection()
{
Assert.NotNull(_fixture.ConnectionString);
}
}
Mocking Dependencies with Moq
Many applications depend on databases, APIs, or external services.
Instead of calling real dependencies, use mocks.
Install Moq:
dotnet add package Moq
Example:
public interface IEmailService
{
bool Send(string email);
}
using Moq;
using Xunit;
public class EmailTests
{
[Fact]
public void SendEmail_ReturnsTrue()
{
var mockService =
new Mock<IEmailService>();
mockService
.Setup(x => x.Send(It.IsAny<string>()))
.Returns(true);
Assert.True(
mockService.Object.Send(
"test@example.com"));
}
}
Best Practices for xUnit Testing
Keep Tests Independent
Tests should not depend on each other.
Follow Naming Conventions
A common format:
MethodName_Scenario_ExpectedResult
Example:
Add_TwoNumbers_ReturnsSum
Test One Thing at a Time
Each test should verify a single behavior.
Avoid External Dependencies
Use mocks instead of databases or APIs whenever possible.
Keep Tests Fast
Unit tests should execute quickly.
Use Arrange-Act-Assert
Maintain consistent structure for readability.
Integrating with CI/CD
xUnit integrates seamlessly with:
- GitHub Actions
- Azure DevOps
- Jenkins
- GitLab CI/CD
Example GitHub Actions command:
- name: Run Tests
run: dotnet test
Automated testing helps catch issues before deployment.
Real-World Benefits of xUnit
Organizations use xUnit to:
- Improve code reliability
- Reduce production bugs
- Enable safe refactoring
- Increase deployment confidence
- Support Agile and DevOps workflows
A well-tested application is easier to maintain and scale over time.
Conclusion
xUnit is one of the most powerful and widely used testing frameworks in the .NET ecosystem. By writing unit tests early and consistently, developers can improve application quality, reduce bugs, and build confidence in their code.