Unit tests are a vital step in development, allowing you to check small, specific functionalities. Here’s how to get started in .NET MAUI.
There are different types of tests in software applications, including unit tests, integration tests and user interface tests. Today, we’ll focus on unit tests, one of the most common types.
Unit tests allow us to examine small pieces of code individually—such as functions or methods—to verify specific functionalities. This checks that these code units behave as expected and helps prevent errors from spreading throughout the application.
The main advantages of unit testing include:
When developing your app, it’s recommended to incorporate unit tests into your workflow. Add them to your “must-have” list before considering a piece of code functionality complete. These tests can serve double duty as design documentation and functional specifications.
First of all, what is xUnit? xUnit is a widely-used unit testing framework for writing and running automated tests in .NET applications.
To add xUnit tests to your .NET MAUI solution, you have two options:
Use Visual Studio to add a new xUnit test project to your solution. Navigate to Web and Console ➡️ Test ➡️ xUnit Test Project.
Create the xUnit project from the .NET CLI. For more information, see Unit testing C# in .NET using dotnet test and xUnit.
The created project must include a project file (.csproj) that resembles the following example:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>
⚠️ A key element to note in the code is the TargetFramework
property. This sets the project’s framework and should correspond to the latest version of .NET installed on your computer.
There are two main approaches to structuring your application for unit testing:
To add unit tests in a .NET MAUI project, you need to modify the build properties. This applies whether the code you’re testing is in the application project or a class library used by the application. Specifically, add the $(TargetFramework)
value from the xUnit test project file to the $(TargetFrameworks)
property in the corresponding project file (either the application or the class library).
Below I show you an example of how it should look:
<TargetFrameworks>net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
In this example, we added net8.0
to $(TargetFrameworks)
. You’ll need to add a reference to your .NET MAUI class library or app project from your xUnit test project.
To target the .NET MAUI application project, we need one additional step. We must modify the .NET MAUI app project to prevent it from generating an executable for the target framework used by the xUnit test project. Simply add a condition to the $(OutputType)
build property in the .NET MAUI app project file, as follows:
<OutputType Condition="'$(TargetFramework)' != 'net8.0'">Exe</OutputType>
xUnit supports two main types of unit tests: facts and theories.
Unit tests must be placed in your xUnit test project and must contain either the [Fact]
or [Theory]
attribute, depending on the type of test you need to create.
The [Fact]
attribute designates a method as a unit test.
Let’s examine an example using [Fact]
, which denotes tests with invariant conditions—those that are always true. Our example includes two scenarios:
PassTest Method: This method demonstrates that 2 + 2 equals 4, resulting in a successful test. To verify this, we use the Assert
class, which allows us to check if the result of an operation or the state of an application matches our test expectations.
FailingTest: This method attempts to assert that 2 + 2 equals 5, which is incorrect and results in a failed test. It also uses the Assert
class to verify the result.
Let’s see what this looks like in code:
namespace MyUnitTests
{
public class MyTests
{
[Fact]
public void PassingTest()
{
Assert.AreEqual(4, 2+2);
}
[Fact]
public void FailingTest()
{
Assert.AreEqual(5, 2+2);
}
}
}
Unlike [Fact]
, which is a test executed only once, the [Theory]
attribute allows you to test the same logic with multiple inputs, verifying that the code works correctly in various scenarios.
In the example below, we test different scenarios using the [InlineData]
attribute to specify the data passed as parameters to the test method. We’ll create a MyTheoryTest
method that accepts an integer value as a parameter (the same parameter you pass using [InlineData]
).
After passing all the values you want to test, you simply indicate what you want to confirm—in this case, whether the value passed by parameter is an odd number.
Here’s how it looks in code:
namespace MyUnitTests
{
public class MyTests
{
[Theory]
[InlineData(3)]
[InlineData(4)]
[InlineData(5)]
public void MyTheoryTest(int value)
{
Assert.True(value % 2 == 1);
}
}
}
And your tests are done! 😎
As you’ve seen in the previous examples, these tests follow a specific structure. This organization is based on the Arrange-Act-Assert pattern.
Unit tests typically follow this Arrange-Act-Assert pattern, which makes the tests readable, self-describing and coherent. Let’s explore their definitions:
Let’s examine one of the examples above to better understand each step in the code:
In this straightforward manner, your code follows the Arrange-Act-Assert (AAA) pattern. 🥰
These tests can be run in two ways:
That’s all! 🎊 You already know how to start with unit testing in your .NET MAUI apps!
Thanks for reading this article! 💚💕
See you next time! 🙋♀️
This article was based on the official documentation:
Leomaris Reyes is a Software Engineer from the Dominican Republic, with more than 5 years of experience. A Xamarin Certified Mobile Developer, she is also the founder of Stemelle, an entity that works with software developers, training and mentoring with a main goal of including women in Tech. Leomaris really loves learning new things! 💚💕 You can follow her: Twitter, LinkedIn , AskXammy and Medium.