Setup .NET Core 2.1 project and test with XUnit on Linux VM

Working with .NET Core is so much fun, but it can be a little bit tricky sometimes, unit test projects with XUnit, how am I supposed to run the tests from CLI using .NET Core 2.1 runtime?
In this post I am going to quickly setup a .NET Core test project along with an XUnit test project and will run the tests on a Linux VM that I am going to setup with HashiCorp Vagrant.

I will not go into many details here, rather I should jump quickly on the tutorial, which I build through my Windows 10 OS.
Though I will provide some honorable mentions to the tools I will be using

Make sure to have the first two installed. If you do not need VirtualBox, let’s say you are running a Hyper-V, follow along, but you are on your own setting up the VM.
Let’s jump into setting this up.

Setup

First thing is to create the workspace. I will create my workspace at D:\Dev\Vagrant, which is a location that already existed on my machine. I will create a new folder with name bp-dotnet-sample, via command prompt,

$ mkdir bp-dotnet-sample
$ cd bp-dotnet-sample
view raw install.bat hosted with ❤ by GitHub

Now it’s time to setup the Vagrantfile, so type

vagrant init
view raw install.bat hosted with ❤ by GitHub

This will create the vagrant file in the directory. This is a Ruby code based file, so, next up, I will setup a simple Ubuntu Linux VM via that. Boilerplate file is too noisy, too many comments, just butcher them out, leave what is required and setup the VM, like so

# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility).
Vagrant.configure("2") do |config|
config.vm.define "xunit" do |test|
test.vm.box = "ubuntu/trusty64"
test.vm.hostname = "xunit"
test.vm.network "private_network", ip: "192.168.56.10"
end
end
view raw Vagrantfile hosted with ❤ by GitHub

Configuration file is in place, let’s build this bad boy by typing

vagrant up
view raw install.bat hosted with ❤ by GitHub

This will take a while, in case you don’t have the OS image already, depending on your network speed.
When it finally fetches the image, vagrant will create and run the VM, which you will be able to see via VirtualBox.

It’s time to login into the VM, install .NET Core SDK and start coding.

vagrant ssh xunit
view raw install.bat hosted with ❤ by GitHub

It asks for your password, and I provide vagrant as the one. By default, when vagrant provisions new VMs, if not instructed otherwise, it sets username and password as vagrant.

I am logged in now

Next up, I will install .NET Core SDK 2.1
First, check the release distro, by typing

lsb_release -a
view raw install.bat hosted with ❤ by GitHub

I have installed an Ubuntu 14.04 version as it seems

I will follow the official instructions, so first register the Microsoft product key as trusted

$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
view raw install.sh hosted with ❤ by GitHub

And then the desired version package feed

sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
view raw install.sh hosted with ❤ by GitHub

Also, update the apt-get package tool

$ sudo apt-get install apt-transport-https
$ sudo apt-get update
view raw install.sh hosted with ❤ by GitHub

And now install .NET Core SDK

sudo apt-get install dotnet-runtime-2.1.0-preview1-26216-03
view raw install.sh hosted with ❤ by GitHub

After it is done, check if .NET Core SDK is indeed installed

dotnet --info
view raw install.bat hosted with ❤ by GitHub

Setting up the project

I will create a .NET Standard 2.0 class library, a test project that references that library and a solution to group those projects together.

Create a new working directory

mkdir sample && cd sample/
view raw install.sh hosted with ❤ by GitHub

Now the class library project, named Sample.csproj

dotnet new classlib -n Sample
view raw install.sh hosted with ❤ by GitHub

And the corresponding XUnit test project named Sample.Unit.Tests.csproj

dotnet new xunit -n Sample.Unit.Tests
view raw install.sh hosted with ❤ by GitHub

And add reference to the Sample.csproj

dotnet add Sample.Unit.Tests/Sample.Unit.Tests.csproj reference Sample/Sample.csproj
view raw install.sh hosted with ❤ by GitHub

Finally, I will create a new solution named Samples.sln and add both projects there

dotnet new sln Samples.sln
view raw install.sh hosted with ❤ by GitHub

I have two .csproj files in the directory, so I want to add all of them without too much fuss, thus I use a globbing pattern

dotnet sln Samples.sln add **/*.csproj
view raw install.sh hosted with ❤ by GitHub

Next step is to add a simple class in the class library with a simple method that returns the result of adding two numbers.

$ cd Sample
$ rm Class1.cs
$ touch Calculator.cs
$ vim Calculator.cs
view raw install.sh hosted with ❤ by GitHub

And this is the source code

namespace Sample {
using System;
public class Calculator {
public int Add(int a, int b) => a + b;
}
}
view raw Calculator.cs hosted with ❤ by GitHub

Next step is to make the XUnit test project use the 2.1-preview runtime. Bear in mind that test projects must have a runtime and in this case, I will update the runtime from .netcoreapp2.0 to .netcoreapp2.1.

$ cd ..
$ cd Sample.Unit.Tests/
$ vim Sample.Unit.Tests.csproj
view raw install.sh hosted with ❤ by GitHub

I’ve update .csproj to the following. Notice that I use the latest pre-release packages. You don’t have to do this, stable release packages still work.

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0-preview-20180307-01" />
<PackageReference Include="xunit" Version="2.4.0-beta.1.build3958" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0-beta.1.build3958" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.4.0-beta.1.build3958" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sample\Sample.csproj" />
</ItemGroup>
</Project>

In the same project, add a simple unit test for the Add method

$ rm UnitTest1.cs
$ mkdir CalculatorTests
$ touch Add.cs
$ vim Add.cs
view raw install.sh hosted with ❤ by GitHub

And the test code is

namespace Sample.Unit.Tests {
using System;
using Xunit;
using Sample;
public class Add {
[Theory]
[InlineData(1, 1, 2)]
[InlineData(3, 2, 5)]
[InlineData(6, 8, 14)]
public void TwoInputNumbersProvideResult(int a, int b, int expected) {
// Arrange
var calculator = new Calculator();
// Act
var result = calculator.Add(a, b);
// Assert
Assert.Equal(expected, result);
}
}
}
view raw Add.cs hosted with ❤ by GitHub

I will head back to the solution now and build the project. Please note that dotnet build does perform a restore unless you specifically instruct it not to do it by using the --no-restore option. I will let the build command handle package restore for me.

$ cd ..
$ dotnet build
view raw install.sh hosted with ❤ by GitHub

Finally, I will run the tests. First, I will take a peak on how many and which tests are going to execute and then I will run them. dotnet test -t does not run the test, rather it discovers them.

$ dotnet test Sample.Unit.Tests/Sample.Unit.Tests.csproj -t
$ dotnet test Sample.Unit.Tests/Sample.Unit.Tests.csproj
view raw install.sh hosted with ❤ by GitHub

Tests run successfully.
Fortunately, it wasn’t that difficult, as the CLI provides the xunit template, so you can avoid boilerplate code. Template installs the XUnit framework, but also installs xunit.runner.visualstudio which is the XUnit adapter and the Microsoft.NET.Test.Sdk which provides MSbuild targets and properties for building .NET test projects. Without those two, you won’t be able to run tests, as dotnet test requires a test adapter in place and the MSBuild targets.

Unfortunately though, there is no any CLI template ready to .NET Core 2.1-preview, so you have to modify the runtime, and in some cases the packages, yourself. Just change the runtime to .netcoreapp2.1, and packages to appropriate versions.

Summary

In this post I walked you through getting a Linux VM up and running with Vagrant, install .NET Core SDK, create a project and a test project that uses XUnit, set it to .NET Core 2.1-preview, restore, build and run tests.