Table of Contents

    xUnit.NET is a free, open-source platform available to perform unit testing for our .NET applications. It supports multiple languages like c#, VB.NET & other .NET languages. This article will explore how to create a test project using xUnit.NET and perform the unit tests on methods developed in some other projects. Before starting with some practical examples, let's understand how many types of tests there are in xUnit.NET. There are two types of tests, as listed below:

    • Facts: These are the tests that are always true. Also, these tests don't accept parameters, meaning whatever data we need to test against our logic must be hard-coded inside the examination.
    • Theory: These are the conditional tests true for a specific data set. These are parameterized tests that can accept outside parameters. It can accept the parameters in various ways, which we will discuss later in this document.

    Let's create a new project to understand how we can perform unit testing using xUnit.NET.

    First, open Visual Studio and create a new project. 

    Step 1: Select "C#" as a programming language in the first drop-down. If C# were selected as a default programming language at the time of Visual Studio installation, it would be selected by default.

    Step 2: Select the project type "Test" in the third drop-down to filter the list of project types below. By default, you will find Web selected in the drop-down.

    Step 3: Select "xUnit Test Project" from the filtered project type list and click "Next."

    Step 4: Name your project, check the checkbox to place the solution in the same directory, and click "Next."

    Step 5: Select the target framework and click "Create" to create your project. The target framework is in .NET 6.0, as I am using Visual Studio 2022.

    Step 6: Let's create another project under the same solution in which we will write a few methods on which we will perform our unit tests.

    Step 7: Let's create a class in the web application and write a few methods to multiply and concatenate strings.

    Step 8: Now add this project reference to the test project so we can write a few tests for the methods mentioned above.

    Once the project reference is added to the test project, you will see that the project has been added to the dependencies of the test project. Now we can use the methods created in the class in our tests by referencing the project namespace. If you look at the test project, you will find that a class named "UnitTest1.cs" is already designed. This is the class where we will write our unit tests.

    Step 9: Let's play with some code and check how it works. Here comes a catch; first, we will start with Fact and understand how to test our methods using Fact. Below is the code written in "UnitTest1.cs" to test the methods for passing conditions.

    Now let's try to understand the code and how it will work. At the very start, we are using a few references; one is of xUnit, which is very important as we will find the associated classes required to create and perform the tests in this namespace. Secondly, the reference of the web project we want to test.

    First, we have created the class object whose methods we want to test. Then, we created two tests decorated with the [Fact] attribute, one for multiplying and another for finding specific text in the string. As mentioned earlier, Facts are always accurate, whether they pass or fail. We will see both examples in this article.

    Now, as we know that Fact is a non-parameterized test; you can see in the above code that all the test parameters and expected results are hard-coded in the test itself. So now, let's understand the logic behind both tests.

      • Test 1 (MultiplyPass): Here, we defined three variables two are input, and the third one is the expected output. We called the multiply method from our web project to calculate the result, and then comes the central part; we are using the "Assert" class, which belongs to the xUnit namespace. This class has various methods to perform testing, like comparing the numeric and string data, finding some data, and a few bool-type ways that only resemble and return the response. Here we used the "Equal" method of the "Assert" class to compare whether the output produced by the process matches the expected result or not.
      • Test 2 (FindPass): There are also three variables: two are input, and the third is to search. Here we used the concrete method from our web project, which will return the concatenated string, and using the "Contains" method of "Assert," we will test whether the expected text exists in the supplied series or not.
      The next step is to build both the project and run the test. So let's first build both the projects and solutions also. Once the build is successful, it's time to execute the unit tests we have created. Now the question comes up, how to do that?

        It's very simple; like Solution Explorer, xUnit.NET also provides Test Explorer, where we will execute and perform our tests. Let me show you where you will find the Test Explorer.

        Step 10: Now open the Text Explorer, and you will find your test project and all your tests there. But, you will find their status as "No Run" because we have not yet executed our tests.

        Let's try running the test and see what happens.

        Here we can see that both our tests are passed. Now let's write a few tests that will fail in the run.

        We have just changed the expected result here and will run the test again.

        Here we can see that two tests out of four failed due to incorrect output from the method. It also displays the test failure details to analyze and identify the appropriate fix wherever needed. This was all about the Fact test type; in the next topic, we will discuss Theory and the various ways to pass parameters to the Theory test.

        As mentioned at the document's start, theories are parameterized tests where we can pass multiple parameters to our tests instead of hard-coding them inside the examination. Therefore, while creating a Theory, you must pass at least one set of parameters to the Theory. There are various ways of passing parameters to the theories, as listed below:


          • This is the simplest way to pass parameters to any Theory. Using InlineData, we pass the parameters as an array to the Theory. The critical point to note here is that the length and the type of the array must match the parameters defined for the Theory. Let's create a Theory and pass the test data using the InlineData attribute.

          In the above example, we passed two sets of data to a single Theory to test, out of which one passed and the other one failed. Note that each set of InlineData creates a separate execution of MultiplyTheory.

          Also, as mentioned, in case of an incorrect number of parameters and/or wrong data type, the debugger itself will show the error indicating that the InlineData does not match the method parameters as shown below.


          If we do not want to pass constants as the testing parameters to the method, the alternative way is to use ClassData. This attribute takes the type that xUnit will use to get the data. To implement ClassData, we will need to create a class that must implement IEnumerable<object[]> interface. This call will return a list which will be an array of objects which xUnit will use as method parameters to perform the test. Below is the code snippet for using ClassData as a parameter for the Theory.

          While using ClassData, xUnit will call.ToList() on the class provided before executing any Theory instance. As we can see in the above code also, there is a pass and one fail set of parameters which will result in the following:


          The ClassData attribute is easy to pass parameters to the Theories. However, if we don't want to create an additional class for passing the test parameters, we can use the MemberData attribute. MemberData uses static property or method to fetch data for the Theory. The MemberData attribute can only fetch data from IEnumerable<object[]> property in the test class. Let's create a static property in the UnitTest1.cs class, which will return the list of objects to be passed to the Theory.

          As we used the static property in the above example to fetch data for the Theory, we can also use a static method returning IEnumerable<object[]> object. 

          In the above example, we can see that we are passing one additional parameter along with the method name. This parameter indicates how many objects will be picked from the list to test the Theory.

          The above screenshot mentions that there are four objects in the list created. Still, as we passed three as the parameter for MemberData, you can see in the Test Explorer that the Theory got executed for the first three objects only, and the last one was ignored. It was a quick introduction to how we can create a unit testing project using xUnit.NET and use it to test our code written in any .NET language. For more also you can hire .NET Developers from us.

          Why use xUnit.NET:

          xUnit.NET is more flexible than any other unit testing framework as it provides more options to create tests using "Fact" & "Theory." The "Assert" class offers many extensions to create tests like Equal, NotEqual, InRange, NotInRange, Contains, DoesNotContain, and many more. The "Theory" allows us to perform different ways of testing by providing the test parameters using multiple options like InlineData, ClassData & MemberData. In addition, it will enable us to provide dynamic test parameters instead of hard-coding them in the test. The essential factor for using xUnit.NET is that it is more extensible than NUnit and MSTest frameworks.

          About Author

          Manektech Team

          Milan Shah

          Chief Technical Officer

          Milan Shah is Chief Technical Officer at ManekTech, having 18+ years experience in .Net department and technical expertise with increasing leadership responsibility. Having an experience of business processes of various Domains like, Online ticket booking Industry, Law-Firm Industry and Transport & Logistics.

          Subscribe to Our Newsletter!

          Join us to stay updated with our latest blog updates, marketing tips, service tips, trends, news and announcements!

          OUR OFFICES

          ManekTech's Global Presence


          4100 NW Loop 410, Suite 200, San Antonio, Texas, USA 78229


          7 Artisan Place Harrow, HA3 5DS


          4th Floor, Timber Point, Prahaladnagar Road, Ahmedabad, Gujarat - 380015


          Franz-Joseph-Strasse, 11,Munich, 80801, Germany

          South Africa

          The Business Centre No 1. Bridgeway Road, Bridgeway Precint, Century City, Cape Town, South Africa, 7446