Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
May 20, 2021 02:22 am GMT

.NET Core Apps on Linux

One of the great benefits in working with .NET Core is knowing that your code will be cross platform. In particular it will run on Linux. This opens up a lot of possibilities. But does it really run on Linux if you have never seen it run? But even if you have seen it run, is it really working if you have never run the unit tests on Linux? In my way of looking at the worldno.

So in this post I will lay out how to get your cross platform .NET Core apps running and tested on Linux in the most straightforward and efficient way.

The approach is to develop code on Windows and test in Linux containers. This is the best combination in my view. So on your windows dev box the set up you need is Hyper-V and Docker. Getting this setup right is not without its challenges which I will not get into here, but I am pleased to report that once you get this working it stays working and I have had this setup working for years now through all manner of Windows and Docker updates.

image

Also needed are the dotnet CLI and VS Code for this optimum (in my view) setup.

image

All the code for this tutorial can be found at https://github.com/bobrundle/dotnettolinux

I'll start by creating a simple console app that adds the numbers that appear as arguments.

image

In VS Code

image

Build and run on windows

image

Here is where it gets interesting. Create a dockerfile for Linux deployment

image

Build a Linux docker image

image

Let's try running it

image

Oops. ICU stands for Internationalization components for Unicode which is used to handle culture dependent APIs. .NET 5.0 requires ICU by default and it is not available by default on Linux. For a simple app such as ours, the easiest thing to do is disable globalization support.

To disable globalization support we need to add another property to our add.csproj project file

Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <OutputType>Exe</OutputType>    <TargetFramework>net5.0</TargetFramework>    <InvariantGlobalization>true</InvariantGlobalization>  </PropertyGroup></Project>

Now lets build and run again

image

Now let's add unit tests. You test-first wingnuts will be very disappointed that I didn't write these first, but I am simply not a test first guy. I could say more but need to stay focused.

image

Need to add a project reference to add.csproj

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>net5.0</TargetFramework>    <IsPackable>false</IsPackable>  </PropertyGroup>  <ItemGroup>    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />    <PackageReference Include="xunit" Version="2.4.1" />    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>      <PrivateAssets>all</PrivateAssets>    </PackageReference>    <PackageReference Include="coverlet.collector" Version="1.3.0">      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>      <PrivateAssets>all</PrivateAssets>    </PackageReference>  </ItemGroup>  <ItemGroup>    <ProjectReference Include="../add/add.csproj"/>  </ItemGroup></Project>

Our unit tests

using System;using Xunit;using add;using System.IO;namespace AddTests{    public class ProgramTests    {        [Theory]        [InlineData(new string[] {}, "0",0)]        [InlineData(new string[] {"1","2","3"}, "6",0)]        [InlineData(new string[] {"1","2","a"}, "",1)]        [InlineData(new string[] {"1.1","2.2","3.3"}, "6.6",0)]        [InlineData(new string[] {"-1e6","1e6"}, "0",0)]        public void MainTest(string[] args0, string r0, int e0)        {            string outfile = Path.GetTempFileName();            var outstream = File.CreateText(outfile);            Console.SetOut(outstream);            int e1 = Program.Main(args0);            Console.Out.Close();            string r1 = File.ReadAllText(outfile);            Assert.Equal(e0, e1);            if(e0 == 0)            {                Assert.Equal(r0 + Environment.NewLine,r1);                }        }    }}

Build the unit tests and run them

image

To run the unit tests in Linux we need to more than move binarieswe have to setup a development environment and build the code before running the tests. To do this we need a Docker file in the parent directory to both code and test folders.

image

The Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:5.0WORKDIR /srcCOPY /add addCOPY /addtests addtestsWORKDIR /src/addtestsCMD ["dotnet","test"]

Build and run on Linux

image

Summary and Discussion

To recap:

  1. A simple Windows console app was created, built and run on Windows.
  2. The console app was built for Linux on Windows and run in a Linux container.
  3. A xUnit testing library was created to run tests against the console app. It was built and run on Windows.
  4. The source for both the console app and the xUnit tests were built and run in a Linux container.

The following questions about this approach come to mind...

Why are you not a test-first guy? My answer is too long to be considered here.

Your "unit tests" are actually integration tests! This is semantics. What we can agree on is 100% code coverage is the gold standard of automated testing and this has been achieved in this example.

What about macOS? You cannot run macOS containers on Windows. You can only run macOS containers on Macs. There might be a way to test all 3 platforms (Windows, Linux, macOS) on a Mac with containers. I will experiment when I get a chance.

Why build in the Linux container? Why not simply use a test runner to run the binaries? Indeed, this is a good idea. I simply don't know how to get this to work with xUnit.

Why not construct a CI/CD pipeline to build and test on Windows and Linux in the cloud? Indeed, the next logical step. However, you still cannot reach macOS in the cloud.

I hope what I have done is useful and addresses some questions you might have. I spent about a day researching the various aspects of this problem. I came to this issue when I was designing a command line tool for Windows and came to realize that the tool would be useful on Linux. Then I began to look into building and testing on Linux and discovered the approach was not well documented and not straight-forward and so suggested a post to capture the learnings.


Original Link: https://dev.to/bobrundle/net-core-apps-on-linux-1a0d

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To