Getting started with xUnit.net (.NET Core / ASP.NET Core)

In this article, we will demonstrate getting started with xUnit.net, showing you how to write and run your first set of unit tests for your .NET Core applications.

Note: Specific versions of xUnit.net only support specific versions of .NET CLI.

The version compatibility list is:

dotnet --version xunit packages dotnet-test-xunit package
1.0.0-preview1-002702 2.1.0 1.0.0-rc2-build10025
1.0.0-preview2-003121
1.0.0-preview2-003131
2.2.0-beta2-build3300 2.2.0-preview2-build1029

To run tests from the current folder, type dotnet test; to run tests from an arbitrary folder, type dotnet test folder. You can pass command line options to these commands; type dotnet test -help for a full list of supported commands.

The examples shown here are done with xUnit.net 2.2 Beta 2, xUnit.net .NET CLI runner 2.2 Preview 2, and .NET CLI 1.0 Preview 2 (including .NET Core 1.0 RTM). Attempting to use any version of .NET CLI other than the supported version will result in indeterminate behavior, and is not officially supported.

Create a class library project

Let's start by creating a .NET Core Class Library application. Open Visual Studio, and choose File > New > Project:

Add a reference to xUnit.net

In Solution Explorer, find and open the project.json file:

Replace the contents of your project.json file with the ones listed below:

{
    "version": "1.0.0-*",
    "testRunner": "xunit",
    "dependencies": {
        "xunit": "2.2.0-beta2-build3300",
        "dotnet-test-xunit": "2.2.0-preview2-build1029"
    },
    "frameworks": {
        "netcoreapp1.0": {
            "dependencies": {
                "Microsoft.NETCore.App": {
                    "type": "platform",
                    "version": "1.0.0"
                }
            }
        }
    }
}
You may have noticed that part of what we did here was mark your class library as a .NET Core Application (the netcoreapp1.0 framework). When using .NET CLI for testing, unit test projects are actually an application*, not a class library. If you forget to make this change, the compiler will tell you that dotnet-test-xunit is not compatible with your class library project. We tell Visual Studio to generate a class library, though, because it most closely matches our desired project structure.

* The application's Main function is provided by the xUnit.net runner, not by you.

Write your first tests

When you created the project, Visual Studio automatically created a file named Class1.cs and opened it for you. Inside this class, add a couple tests:

using Xunit;

namespace MyFirstDotNetCoreTests
{
    public class Class1
    {
        [Fact]
        public void PassingTest()
        {
            Assert.Equal(4, Add(2, 2));
        }

        [Fact]
        public void FailingTest()
        {
            Assert.Equal(5, Add(2, 2));
        }

        int Add(int x, int y)
        {
            return x + y;
        }
    }
}

Build the solution to ensure that the code compiles. Now that you've written the first test, we need a way to run it.

Run tests from the console

Open a command prompt or PowerShell command window. In the window, navigate to folder containing the source code of your test project (this will usually be in a folder below the src folder, in your solution folder).

To run the .NET CLI test runner, type dotnet test, as shown below:

> dotnet test
xUnit.net .NET CLI test runner (64-bit .NET Core win10-x64)
  Discovering: MyFirstDotNetCoreTests
  Discovered:  MyFirstDotNetCoreTests
  Starting:    MyFirstDotNetCoreTests
    MyFirstDotNetCoreTests.Class1.FailingTest [FAIL]
      Assert.Equal() Failure
      Expected: 5
      Actual:   4
      Stack Trace:
        C:\Samples\MyFirstDotNetCoreTests\src\MyFirstDotNetCoreTests\Class1.cs(16,0): at MyFirstDotNetCoreTests.Class1.FailingTest()
  Finished:    MyFirstDotNetCoreTests
=== TEST EXECUTION SUMMARY ===
   MyFirstDotNetCoreTests  Total: 2, Errors: 0, Failed: 1, Skipped: 0, Time: 0.167s

Now that we've gotten your first unit tests to run, let's introduce one more way to write tests: using theories.

Write your first theory

You may have wondered why your first unit tests use an attribute named [Fact] rather than one with a more traditional name like Test. xUnit.net includes support for two different major types of unit tests: facts and theories. When describing the difference between facts and theories, we like to say:

Facts are tests which are always true. They test invariant conditions.

Theories are tests which are only true for a particular set of data.

A good example of this testing numeric algorithms. Let's say you want to test an algorithm which determines whether a number is odd or not. If you're writing the positive-side tests (odd numbers), then feeding even numbers into the test would cause it fail, and not because the test or algorithm is wrong.

Let's add a theory to our existing facts (including a bit of bad data, so we can see it fail):

[Theory]
[InlineData(3)]
[InlineData(5)]
[InlineData(6)]
public void MyFirstTheory(int value)
{
    Assert.True(IsOdd(value));
}

bool IsOdd(int value)
{
    return value % 2 == 1;
}

This time when we compile and run our tests, we see a second failure, for our theory that was given 6:

xUnit.net .NET CLI test runner (64-bit .NET Core win10-x64)
  Discovering: MyFirstDotNetCoreTests
  Discovered:  MyFirstDotNetCoreTests
  Starting:    MyFirstDotNetCoreTests
    MyFirstDotNetCoreTests.Class1.MyFirstTheory(value: 6) [FAIL]
      Assert.True() Failure
      Expected: True
      Actual:   False
      Stack Trace:
        C:\Samples\MyFirstDotNetCoreTests\src\MyFirstDotNetCoreTests\Class1.cs(30,0): at MyFirstDotNetCoreTests.Class1.MyFirstTheory(Int32 value)
    MyFirstDotNetCoreTests.Class1.FailingTest [FAIL]
      Assert.Equal() Failure
      Expected: 5
      Actual:   4
      Stack Trace:
        C:\Samples\MyFirstDotNetCoreTests\src\MyFirstDotNetCoreTests\Class1.cs(16,0): at MyFirstDotNetCoreTests.Class1.FailingTest()
  Finished:    MyFirstDotNetCoreTests
=== TEST EXECUTION SUMMARY ===
   MyFirstDotNetCoreTests  Total: 5, Errors: 0, Failed: 2, Skipped: 0, Time: 0.173s

Although we've only written 3 test methods, the console runner actually ran 5 tests; that's because each theory with its data set is a separate test. Note also that the runner tells you exactly which set of data failed, because it includes the parameter values in the name of the test.

Run tests in Visual Studio

The same NuGet package which allows you to run tests from the console also allows you to run tests from within Visual Studio. Show the Test Explorer window by choosing Test > Windows > Test Explorer. The Test Explorer window will show inside Visual Studio, and your test should be visible (if they're not, try building your project to kick off the test discovery process). It should look something like this:

If you click the Run All link in the Test Explorer window, it will run your tests and show you success and failure. You can click on an individual test result to get failure information as well as stack trace information:

Adding a configuration file

The .NET CLI runner supports JSON-based configuration files. When using a configuration file with .NET CLI, you need to instruct the build system to copy the config file into the bin folder when it builds. To do this, add the following to the top-level of project.json file:

{
    "buildOptions": {
        "copyToOutput": {
            "include": [ "xunit.runner.json" ]
        }
    }
}

Targeting desktop .NET

The .NET CLI runner is capable of running tests which target desktop .NET (minimum version 4.5.1), in addition to .NET Core. To target desktop .NET, use this frameworks section instead:

{
    "frameworks": {
        "net451": {
            "dependencies": {
                "Microsoft.NETCore.Platforms": "1.0.1"
            }
        }
    }
}

You can target both net4xx and netcoreapp simply by adding both frameworks together in your project.json file. When you run dotnet test with multiple framework entries, the system will run all your framework tests, one after another.

Console runner return codes

The following return codes are used by the console runner:

Return code Meaning
0 The tests ran successfully.
1 One or more of the tests failed.
2 The help page was shown, either because it was requested, or because the user did not provide any command line arguments.
3 There was a problem with one of the command line options passed to the runner.
4 There was a problem loading one or more of the test assemblies (for example, if a 64-bit only assembly is run with the 32-bit test runner).
Copyright © 2016 .NET Foundation. Contributions welcomed at https://github.com/xunit/xunit.github.io.