A Comprehensive Tutorial for Modern Unit Testing
XUnit is a free, open-source, extensible unit testing tool for the .NET Framework, .NET Core, and Mono. It is the latest unit testing tool from the creator of NUnit and the initiator of the .NET Foundation.
This tutorial will guide you through setting up and using XUnit for effective unit testing in your .NET projects. We'll cover basic test writing, assertions, and some advanced concepts.
Create a new .NET project (e.g., a Class Library) for your application code and a separate .NET Core Test project for your tests.
You can use the .NET CLI:
dotnet new classlib -n MyApplication
dotnet new xunit -n MyTests
cd MyTests
dotnet add reference ../MyApplication/MyApplication.csproj
Let's assume you have a simple class in MyApplication
:
// MyApplication/Calculator.cs
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Now, write a corresponding test in your MyTests
project:
// MyTests/CalculatorTests.cs
using Xunit;
using MyApplication;
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsCorrectSum()
{
// Arrange
var calculator = new Calculator();
int a = 5;
int b = 10;
int expected = 15;
// Act
int actual = calculator.Add(a, b);
// Assert
Assert.Equal(expected, actual);
}
}
The [Fact]
attribute marks a method as a test case. The Arrange-Act-Assert (AAA) pattern is a common way to structure tests.
Navigate to your test project directory in the terminal and run:
dotnet test
You should see the test run and pass.
XUnit provides a rich set of assertion methods in the Assert
class. Some common ones include:
Assert.Equal(expected, actual)
Assert.True(condition)
Assert.False(condition)
Assert.NotNull(object)
Assert.Throws<TException>(Action)
- For testing exceptions.Example using Assert.Throws
:
[Fact]
public void Divide_ByZero_ThrowsDivideByZeroException()
{
var calculator = new Calculator();
Assert.Throws<DivideByZeroException>(() => calculator.Divide(10, 0));
}
For scenarios where you need to share setup and teardown logic across multiple tests within the same test class, you can use collection fixtures.
This is particularly useful for database connections or other expensive resources.
[Theory]
allows you to run the same test multiple times with different inputs. This is often combined with data attributes like [InlineData]
and [MemberData]
.
public class CalculatorTests
{
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, 1, 0)]
[InlineData(5, 5, 10)]
public void Add_Theory_ReturnsCorrectSum(int a, int b, int expected)
{
var calculator = new Calculator();
Assert.Equal(expected, calculator.Add(a, b));
}
}
XUnit is a powerful and flexible unit testing framework that can significantly improve the reliability and maintainability of your .NET applications. By following the steps and concepts outlined in this tutorial, you'll be well on your way to writing effective unit tests.
For more advanced topics, refer to the official XUnit documentation.