Let’s be real, bugs in code are annoying. They break stuff, cause late-night headaches, and often lead to endless Slack messages asking, “Why is this broken?” One of the best ways to avoid all that drama? Unit testing.
In this guide, we’ll walk through unit testing in .NET using xUnit, one of the most popular testing libraries out there. Don’t worry, we’ll keep it friendly, simple, and beginner-approved.
What’s Unit Testing Anyway?
Unit testing is all about testing individual pieces of code, usually methods or functions, to make sure they behave correctly. Think of it like checking each Lego block before building the entire castle.
Here’s why unit tests matter:
- Catch bugs early
- Improve code reliability
- Make refactoring safer
- Document expected behaviour
Why Use xUnit for .NET?
.NET supports a few testing frameworks, but xUnit stands out for being:
- Open-source and super fast
- Clean and readable syntax
- Fully supported by Microsoft
- Easy to integrate with test runners and CI/CD pipelines
Setting Up xUnit in Your .NET Project
Okay, enough talk, let’s get to work.
1. Create a .NET Solution
If you don’t already have a .NET project, go ahead and create one:
bash
CopyEdit
dotnet new sln -n MyApp
dotnet new classlib -n MyApp.Core
dotnet new xunit -n MyApp.Tests
dotnet sln add MyApp.Core/MyApp.Core.csproj
dotnet sln add MyApp.Tests/MyApp.Tests. csproj
2. Add a Reference to the Main Project
Your test project needs to “know” about your app code:
bash
CopyEdit
dotnet add MyApp.Tests/MyApp.Tests.csproj reference MyApp.Core/MyApp.Core.csproj
That’s it! Now you’re ready to write your first test.
Writing Your First xUnit Test
Let’s say you’ve got a simple calculator:
csharp
CopyEdit
// File: Calculator.cs
namespace MyApp.Core
{
public class Calculator
{
public int Add(int a, int b) => a + b;
}
}
Here’s how you test it using xUnit:
csharp
CopyEdit
// File: CalculatorTests.cs
using MyApp.Core;
using Xunit;
namespace MyApp.Tests
{
public class CalculatorTests
{
[Fact]
public void Add_ShouldReturnCorrectSum()
{
// Arrange
var calc = new Calculator();
// Act
int result = calc.Add(2, 3);
// Assert
Assert.Equal(5, result);
}
}
}
What’s Going On?
- [Fact] tells xUnit that this is a test method.
- Arrange, Act, Assert is the golden pattern for writing clean, clear tests.
Running the Tests
To run your tests, just use the command:
bash
CopyEdit
dotnet test
You’ll get output like:
bash
CopyEdit
Passed! 1 test ran in 50ms.
And just like that, you’ve written and passed your first unit test!
xUnit Attributes You Should Know
Here are some of the key attributes you’ll use often:
Attribute | What it does |
[Fact] | Marks a basic test method |
[Theory] | Used for parameterised tests |
[InlineData] | Provides test data for Theory |
Example of a [Theory] test:
csharp
CopyEdit
[Theory]
[InlineData(2, 3, 5)]
[InlineData(-1, -1, -2)]
public void Add_MultipleValues_ShouldWork(int a, int b, int expected)
{
var calc = new Calculator();
int result = calc.Add(a, b);
Assert.Equal(expected, result);
}
Common Testing Scenarios
Here’s how to handle real-life stuff you’ll face in testing.
Testing for Exceptions
csharp
CopyEdit
[Fact]
public void Divide_ByZero_ShouldThrow()
{
var calc = new Calculator();
Assert.Throws<DivideByZeroException>(() => calc.Divide(10, 0));
}
Testing Asynchronous Methods
csharp
CopyEdit
[Fact]
public async Task GetDataAsync_ShouldReturnData()
{
var service = new DataService();
var data = await service.GetDataAsync();
Assert.NotNull(data);
}
Mocking with Moq (Bonus Tip)
Sometimes your methods depend on external stuff like databases or APIs. That’s where mocking comes in. A popular tool is Moq.
Install it:
bash
CopyEdit
dotnet add package Moq
Basic usage:
csharp
CopyEdit
var mockRepo = new Mock<IUserRepository>();
mockRepo.Setup(repo => repo.GetUser(1)).Returns(new User { Id = 1, Name = “Alice” });
You can then inject that mock into your service and test it without hitting the real database.
Best Practices for Unit Testing
- Keep tests isolated – test one thing at a time
- Use meaningful names – describe what the test checks
- Avoid magic numbers – use variables or constants
- Don’t over-mock – only mock when needed
- Run tests often – make it part of your dev flow
FAQs
Q1: Can I use xUnit with .NET 6 or 7?
Absolutely! xUnit works great with both.
Q2: What’s the difference between xUnit, NUnit, and MSTest?
They’re all testing frameworks, but xUnit is newer, cleaner, and recommended by the .NET team.
Q3: How do I run tests in Visual Studio?
Just right-click the test project or method and click “Run Tests”. Or use the Test Explorer panel.
Wrapping Things Up
So, that’s the scoop on unit testing in .NET with xUnit. It’s not rocket science, but it is rocket fuel for your code quality. From setting up a test project to writing and running tests, you’re now equipped to make your .NET apps more robust and reliable.