How to use xUnit to run unit testing in .NET and C#

Published: Tuesday 2 April 2024

Software companies all over the world use unit testing to automate tests for their systems.

Therefore if you are a .NET developer, it's essential that you know how to perform unit testing on your code.

In .NET, there are three unit testing frameworks that you can choose from:

  • xUnit
  • nUnit
  • MSTest

This tutorial will focus on xUnit and it will look on how to write unit tests using the Fact and Theory attributes.

In-addition, we'll have a look at some of the different Assert methods which tells you whether a test has passed or not.

Creating an xUnit project in Visual Studio

In Visual Studio, create a new project, and do a search for xUnit. Select the C# template.

Create an xUnit project in Visual Studio

Create an xUnit project in Visual Studio

Go through the steps to create the project.

Creating a class library

With the xUnit project created, we need something to test.

For that, we are going to create a class library.

In Visual Studio, make sure the xUnit test project is open, and right-click on the solution and go to Add and New Project.

Create a class library within a solution in Visual Studio

Create a class library within a solution in Visual Studio

Do a search for Class Library in C# and go through the steps to create the project.

Writing methods to test

In the class library, we are going to create a new class called NumberHelper.

Within that, we are going to write some static methods.

The first method will help us decide whether a number is an odd number or not. We will also write a similar method on even numbers.

The other method will output a string-based rating dependant on a score out of 10.

// NumberHelper.cs
public static class NumberHelper
{
    public static bool IsOddNumber(int number)
    {
        return number % 2 == 1;
    }

    public static bool IsEvenNumber(int number)
    {
        return number % 2 == 0;
    }
	
	public static string RatingScore(int number) => number switch
	{
		< 3 => "Bad",
		>= 3 and < 7 => "Ok",
		>= 7 and <= 10 => "Great",
		_ => "Unknown"
	};
}

Writing these methods will help you with some of the different Assert methods that are available in xUnit.

Writing xUnit tests

Before writing the xUnit tests, make sure you that your xUnit test project has a reference to the class library. This is because we are going to be writing unit tests for the NumberHelper static class.

In the xUnit project, create a new class called NumberHelperFactTests and add these tests:

// NumberHelperFactTests.cs
public class NumberHelperFactTests
{
	public void IsOddNumber_ValueOf3_ShouldReturnTrue()
	{
		// Act
		Assert.True(NumberHelper.IsOddNumber(3));
	}

	public void IsOddNumber_ValueOf6_ShouldReturnFalse()
	{
		// Act
		Assert.False(NumberHelper.IsOddNumber(6));
	}

	public void IsEvenNumber_ValueOf3_ShouldReturnFalse()
	{
		// Act
		Assert.False(NumberHelper.IsEvenNumber(3));
	}

	public void IsEvenNumber_ValueOf6_ShouldReturnTrue()
	{
		// Act
		Assert.True(NumberHelper.IsEvenNumber(6));
	}
}

For this, we have written a number of methods with each one being a separate test.

The first two methods test out the IsOddNumber method and whether passing in a certain number should return true or false.

The other two methods do exactly the same, but this time they test out the IsEvenNumber method.

The Assert.True or Assert.False methods have to match the parameter passed into it for the unit test to be successful.

Using the Fact attribute

At present, these tests won't run.

We need to add the Fact attribute to each of the tests. This tells xUnit that it's a unit test method that needs to be run.

public class NumberHelperFactTests
{
	[Fact]
	public void IsOddNumber_ValueOf3_ShouldReturnTrue()
	{
		// Act
		Assert.True(NumberHelper.IsOddNumber(3));
	}

	[Fact]
	public void IsOddNumber_ValueOf6_ShouldReturnFalse()
	{
		// Act
		Assert.False(NumberHelper.IsOddNumber(6));
	}

	[Fact]
	public void IsEvenNumber_ValueOf3_ShouldReturnFalse()
	{
		// Act
		Assert.False(NumberHelper.IsEvenNumber(3));
	}

	[Fact]
	public void IsEvenNumber_ValueOf6_ShouldReturnTrue()
	{
		// Act
		Assert.True(NumberHelper.IsEvenNumber(6));
	}
}

How to run xUnit tests

With the test methods set up, we can now run them.

In Visual Studio, go to Test and Test Explorer.

This loads up the Test Explorer tab and we can now run the tests.

You should find that all the tests pass.

Passed xUnit tests using Test Explorer in Visual Studio

Passed xUnit tests using Test Explorer in Visual Studio

Multiple xUnit test projects in the same method

The Fact attribute allows us to run one test on that particular method.

But what if we want to run multiple tests on it? There are many numbers we can test to determine whether they are odd or even.

Introducing the Theory attribute

The Theory attribute allows us to do just that.

By adding that alongside the InlineData attribute, it allows us to pass a parameter into the unit test.

And by adding multiple InlineData attributes, we can pass in different parameters to the same method, therefore creating multiple tests on the same method.

// NumberHelperTheoryTests.cs
public class NumberHelperTheoryTests
{
    [Theory]
    [InlineData(3)]
    [InlineData(5)]
    [InlineData(7)]
    public void IsOddNumber_Values_ShouldReturnTrue(int number)
    {
        // Act
        Assert.True(NumberHelper.IsOddNumber(number));
    }

    [Theory]
    [InlineData(2)]
    [InlineData(4)]
    [InlineData(6)]
    public void IsOddNumber_Values_ShouldReturnFalse(int number)
    {
        // Act
        Assert.False(NumberHelper.IsOddNumber(number));
    }

    [Theory]
    [InlineData(3)]
    [InlineData(5)]
    [InlineData(7)]
    public void IsEvenNumber_Values_ShouldReturnFalse(int number)
    {
        // Act
        Assert.False(NumberHelper.IsEvenNumber(number));
    }

    [Theory]
    [InlineData(2)]
    [InlineData(4)]
    [InlineData(6)]
    public void IsEvenNumber_Values_ShouldReturnTrue(int number)
    {
        // Act
        Assert.True(NumberHelper.IsEvenNumber(number));
    }
}

When testing the IsOddNumber method to ensure it returns true, we are passing in 3, 5 and 7 in separate InlineData attributes.

This contributes to three unit tests, and the value in the InlineData attribute gets passed in as the number parameter as part of the method.

We do the same when testing the IsOddNumber expecting the result to return false. This time, we add 2, 4 and 6 to separate InlineData attributes as we don't expect them to be odd numbers.

The exercise is repeated for the IsEvenNumber method.

Different Assert methods

So far, we have used Assert.True and Assert.False methods. But what about some of the other Assert methods?

In NumberHelper class, we created a RatingScore method. We are going to carry out some unit tests by using the Assert.Equal and Assert.NotEqual methods.

Adding Fact tests

In NumberHelperFactTests class, add these test methods to it:

// NumberHelperFactTests.cs
public class NumberHelperFactTests {

	...
	[Fact]
	public void RatingScore_ValueOf7_EqualsGreat()
	{
		Assert.Equal("Great", NumberHelper.RatingScore(7));
	}

	[Fact]
	public void RatingScore_ValueOf7_NotEqualsBad()
	{
		Assert.NotEqual("Bad", NumberHelper.RatingScore(7));
	}
}

The first test ensures that when we pass in 7 into the RatingScore method, it returns Great.

The other test ensures that when we pass 7 into the same method, it does not return Bad.

Adding Theory tests

We can also do the same by adding Theory tests for this method.

In NumberHelperTheoryTests class, add these test methods to it:

// NumberHelperTheoryTests.cs
public class  NumberHelperTheoryTests {

	...
	[Theory]
	[InlineData(2, "Bad")]
	[InlineData(5, "Ok")]
	[InlineData(9, "Great")]
	public void RatingScore_Values_EqualCorrectRating(int number, string rating)
	{
		Assert.Equal(rating, NumberHelper.RatingScore(number));
	}
}

This test passes in two methods. The first is the number and the second is the expected rating response.

This ensures that we can test multiple outcomes from the same test method.

How to debug a test

If a test is not working, you can add breakpoints into the methods that are being tested to step through your code and debug.

In Test Explorer,  you can debug by right-clicking on the tests and clicking on the Debug option.

Debug an xUnit test method in Visual Studio

Debug an xUnit test method in Visual Studio

Watch our video tutorial

Watch our video where you'll learn more about what we covered in this tutorial.

You'll find out how to create an xUnit project and write unit tests using the Fact and Theory attributes.

In-addition, you'll learn about some of the different Assert methods and how to debug a test.

As well as that, you can download the code example which allows you to try out xUnit whilst following the tutorial.