How to correctly implement unit tests for .net Standard Library

Viewed 6091

So as far as I have been understanding from my research. A .net Standard Library can not be used on its own, so it needs to be tested through a different framework, either with .net Framework or .net Core reference. That's just how I interpreted it. Now I am trying to create a Standard Library as I need it to be compatible on most devices as possible, the problem is I don't know how to create the unit tests correctly. Every time I create a MSTest Project I get the following error:

Test run will use DLL(s) built for framework .NETCoreApp,Version=v1.0 and platform X64. Following DLL(s) do not match framework/platform settings. Otchi.Ebml.Tests.dll is built for Framework 2.1 and Platform AnyCPU.

I have experimented a lot with the different architectures and other settings, but nothing seems to work to remove that warning. Am I doing something incorrectly or is there a different, more suitable approach to creating unit tests for a Standard Library

3 Answers

A .NET Standard Library does not contain the necessary components for execution. It only defines the execution patterns. When you deploy to a specific machine / processor architecture, the code must know which instruction set to execute upon.

This is where the .NET framework and .NET core come into play. The .NET framework contains execution details for instruction sets supported by the Microsoft Windows operating system. .NET core, similarly, contains the instruction set for additional architectures not natively supported by Windows.

To write Unit Tests, you need to create a NEW project, either in .NET or in .NET core, to execute your code. If you want to cover all your bases, or if you have some binaries that are compiled differently for different architectures (third party libraries come to mind) then you might want to unit test for multiple distributions.

Your library should be a standalone library. Your unit tests should be executed before you update the library to validate that the code being entered into the library passes. That way anyone who uses the library after that can feel confident that it will work.

Writing unit tests for libraries targeting .NETStandard is tricky since you have to test your code against various implementations of your chosen version of .NETStandard. As already outlined by Zakk Diaz this is due to the fact that .NETStandard merely defines types that are then implemented in actual platforms.

The most common problems are differences in implementation across various platforms like .NETFramework, .NETCore, Mono, etc. However there are also differences in implementations across various versions of platforms that can mess with the way your library works on said platforms (see this example).

This is why running your tests on the lowest version of a platform that implements your chosen version of .NETStandard doesn't quite cut it. You have to take all runtimes into account that your library could be used with.

In general you have two options to solve this issue.

Option 1

Use multi targeting to build your unit test project for all valid runtimes. This also means that you have to have a very big set of target frameworks for your unit test project which will have to be extended whenever new versions of a platform are released.

If you want to cover all relevant scenarios then you'll have dozens of target frameworks and just as many versions of your unit test project being built. Let's just assume that this can get out of hand quickly.

Option 2

Use a unit testing platform that can actually handle .NETStandard by design. Building your unit tests for .NETStandard and having those tests execute on matching runtimes will reduce complexity of your test project.

As of today, most unit testing platforms can't do any of this and you're stuck with Option 1. The one that fits this approach and actually solves your problem is Nuclear.Test.

Please note that Nuclear.Test requires .NETStandard 2.0 and only handles .NETFramework and .NETCore in its current release. This is subject to change however and i'm working on reducing the required version of .NETStandard to 1.0 and include test workers for Mono and UWP as well.

There is an easy bypass,

Create solution with 3 projects:

  1. "Demo.NetStandard"

your .Net Standard library project

  1. "Demo.NetFramework.LinkedToStandard"

new .Net Framework library project, and copy & paste as link all .Net Standard files

  1. "Demo.Tests"

new .Net Framework test project, and Add Reference > "Demo.NetFramework.LinkedToStandard"

This way you write the code straight into your .NetStandard files, and you test it as .NetFramework code.

Related