I want to unit test an asp.net core project that targets the full .net framework. I tried using the "normal" unit test project template and a .net core project as outlined in this blog post, but both attempts fail because the assembly of my web-project cannot be referenced in either of the test projects.
Is there a way to unit test asp.net core apps on the full framework?
Found the solution in the comments section of the same blog post. As I cannot link directly, it is quoted below:
BillyboyD
In case anyone needs to do something similar, I have managed to set this up so I can test my controllers in an ASP.NET Core project that targets the .NET Framework 4.6.1 and also references class libraries that are standard .NET, not .NET core (we will have this hybrid situation for some time!). I am using VS2015 update 3 and .NET Core 1.0. My project.json is:
{
"version": "1.0.0-*",
"testRunner": "mstest",
"dependencies": {
"dotnet-test-mstest": "1.0.1-preview",
"MSTest.TestFramework": "1.0.0-preview",
"MyASP.NetCoreProject": "1.0.0-*"
},
"frameworks": {
"net461": {
"dependencies": {
"MyClassLibrary": {
"target": "project"
}
}
}
}
}
Related
I'm building an ASP.NET Core Web Application (.Net Framework) and am having a hard time figuring out how to hook unit tests up to it. I am targeting the .net framework version 4.6.1
If I create a regular "Class Library" project targeting 4.6.1, as I would for previous version of MVC, it lets me add references to my MVC project (which is part of the same solution) but any namespaces I add through a using statement report an error that I might be missing a reference or using statement. If I double click on the reference under the "References" section in the solution explorer it tells me that the project can't be found or hasn't been build yet.
I tried creating a "Class Library (.NET Core)" but that complains since I'm targeting .Net Framework and not .NET Core. I edited the class libaries Project.json to have it target the .net framework and that lets me add my references and doesn't complain when I the namespaces in a using statement but none of my tests are discovered by the test runner. I've tried both XUnit and NUnit and they both behave the same.
Is it possible to unit test an ASP.Net Core Web Application targeting the .Net Framework 4.6.1 or do I need to commit to the .NET Core?
Edit to add my test class
Here is my test class stripped down to the bare minimum. TestBank.Services is the class I want to test.
using System;
using TestBank.Services;
using Xunit;
namespace TestBankUnitTests
{
public class Class1
{
[Fact]
public void TestA()
{
Assert.True(false);
}
}
}
and here is my project.json
{
"version": "1.0.0-*",
"dependencies": {
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025",
"TestBank": "1.0.0-*"
},
"frameworks": {
"net461": {
}
}
}
Your project.json needs a testRunner setting. Per the project.json documentation, the testRunner setting not only specifies which test framework to use, but also marks the project as a test project.
Try adding it and see if it finds your tests (verified locally that it will not find tests without this setting in the file)
{
"version": "1.0.0-*",
"dependencies": {
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025",
"TestBank": "1.0.0-*"
},
"frameworks": {
"net461": {
}
},
"testRunner": "xunit"
}
I was having a similar issue and found a solution. I am posting it here in case it helps someone. What I have learned is that using an xproj library targeting net461 to test an Asp.Net Core Project (.Net Framework) project targeting net461 and a Windows class library targeting framework 4.61 works but the setup seems to be very finicky and fragile. The key insight for me came from this thread https://github.com/aspnet/Tooling/issues/245 where #BradRem indicated that the folder structure of the projects seemed to the source of issues.
Initially I tried unsuccessfully to use this folder structure:
src
____Asp.Net Core Project (.Net Framework) project targeting Net461
____Windows class library targeting framework 4.61
test
____Core Library used to run xUnit Tests
But when I tried to run the tests using this folder structure it produced the exception that starts off like this:
Unable to start C:\Program Files\dotnet\dotnet.exe
dotnet-test Error: 0 : [ReportingChannel]: Waiting for message failed System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.Stream.ReadByte()
at System.IO.BinaryReader.ReadByte()
at System.IO.BinaryReader.Read7BitEncodedInt()
at System.IO.BinaryReader.ReadString()
at Microsoft.DotNet.Tools.Test.ReportingChannel.ReadMessages()
But when I changed to the following folder structure I was able to get it to work:
src
____Asp.Net Core Project (.Net Framework) project targeting Net461
____Windows class library targeting framework 4.61
____Core Library used to run xUnit Tests
So the key was putting the folder that housed the testing class library in the src folder where the other projects folders were.
That said, the other thing that seemed to make a big difference was to add the references to the other two projects to the Core Library test project at the same time rather than one at a time.
I have found something that works for me.
Inside my test project, my project.json file looks like this:
{
"version": "1.0.0-*",
"testRunner": "xunit",
"dependencies": {
"xunit": "2.2.0-beta2-build3300",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"Ng2a.WebApi": "1.0.0-*"
},
"frameworks": {
"net452": {
}
}
}
'Ng2a.WebApi' is my web api core project. It targets only net452.
The Ng2a.WebApi project.json file looks like this:
"frameworks": {
"net452": {}
},
I'm trying to sign a .net core lib, and I'm just not sure if I did everything correctly
1) using VS Command Promp I called sn -k mykey.snk
2) copied mykey.snk to myproject folder
3) in project.json added keyfile
"frameworks": {
"netstandard1.6": {}
},
"buildOptions": {
"outputName": "MyLib",
"keyFile": "mykey.snk"
}
is this correct, is the library (dll) going to be usable on both .net core and full .net 4.6 apps ?
Yes, this is the correct way. If you look into any ASP.NET Core projects, like Logging, you will find
"buildOptions": {
"keyFile": "../../tools/Key.snk"
...
}
in project.json file, and Key.snk in Tools folder. You also may check .NET Core - strong name assemblies issue.
I want to create data small data access library for Sql Server that wraps standard Sql Client classes, and publish it to NuGet. I want to use this NuGet package both in standard and .Net core apps.
I created class library project with some data access code (it uses System, System.Core, and System.Data) and published it to nugget. I have added System, System.Core, and System.Data as NuGet framework dependencies.
UPDATE - described problems both in RC1 and RC2
In RC1 version it works with 4.6 framework, but I had to remove DNX 5 from package.json.
In RC2 version it works with ASPNET Core (.Net Framework) projects, but when I create ASPNET Core (.Net Core), compilation fails:
Error NU1002 The dependency does not support framework .NETCoreApp,Version=v1.0.
Is there any way to create nugget package that works in both versions?
Since .NET Core 1.0 was just released this week, I'll answer the question in the context of the latest version of the framework.
If you are attempting to target both ASP.NET Core 1.0 and .NET 4.5 you have to define both frameworks separately, including all dependencies each framework build would require.
Here is an example project.json file for a class library project that targets .NET Core Standard 1.5, ASP.NET Core 1.0, .NET 4.5, and .NET 4.0 and has a dependency on the System.Linq.Expressions namespace:
{
"version": "1.0.0-*",
"frameworks": {
"netstandard1.5": {
"imports": "dnxcore50",
"dependencies": {
"NETStandard.Library": "1.6.0",
"System.Linq.Expressions": "4.1.0"
}
},
"netcoreapp1.0": {
"imports": "dnxcore50",
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"System.Linq.Expressions": "4.1.0"
}
},
"net45": {
"frameworkAssemblies": {
"System.Linq.Expressions": ""
}
},
"net40": {}
}
}
With Visual Studio 2017, you can create a .NET Standard project library. You can select the version in the properties of the project.
Such project looks like this :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<AssemblyName>MyAssembly</AssemblyName>
<PackageId>MyPackage</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Copyright>Copyright</Copyright>
<Description>Simple Library</Description>
<Authors>Me</Authors>
<AssemblyVersion>1.1.0</AssemblyVersion>
<FileVersion>1.1.0</FileVersion>
<Version>1.1.0</Version>
<Company>MyCompany</Company>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>
In IDE, you have the pack command on the right click menu or you can type this :
msbuild /t:pack myproject.csproj
Only one package.... to rule them all and... :)
I have a ASP.NET Core API project and I'd like to utilize DirectoryServices and DirectoryServices.AccountManagement namespaces.
After some research I thought I found some project.json references that would work:
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel",
"ef": "EntityFramework.Commands"
},
"frameworks": {
"dnx451": {
"frameworkAssemblies": {
"System.DirectoryServices": "4.0.0.0",
"System.DirectoryServices.AccountManagement": "4.0.0.0"
}
},
"dnxcore50": { },
"net451": { }
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
}
After adding those, code that used classes from those references suggested the namespaces to add to the class:
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
After that intellisense had no complaints and everything looked perfect, however if I try to build or run the project I get "type or namespace name 'DirectoryServices' does not exist in the namespace 'System'" errors.
Is there a resource out there can help me figure out how to implement DirectoryServices and DirectoryServices.AccountManagement in ASP.Net 5?
As a side note I like ASP.NET Core but it seems like having to manually create a json file for references is a big step back from adding references in MVC 5 where you just had to find them and check the box to add them. Makes me wonder if there isn't something I'm missing that can generate that file for you rather than needing to know the exact characters and pasting them in yourself to get things working.
In ASP.NET Core (the new Name for ASP.NET 5 and vNext isn't being officially used for months) a project will by default target multiple platforms.
You have added the references to dnx451 framework moniker, which targets the full .NET 4.5 Framework.
Now if you use
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
inside a *.cs file, it will work for .NET 4.5, but fail for .NET Core, because there is no reference for .NET Core to this namespaces/assemblies. On build always both versions will be compiled, that's why you get this error.
You don't see it in the Visual Studio Editor, because it shows you the code of .NET 4.5 (above the code window is a pulldown menu where you can switch between the target frameworks).
That being said, you have two choices:
You want to target only .NET 4.5
In this case, you just delete the dnxcore50 moniker from your frameworks section of the project.json file (net451 too because it's for class libraries only). This will turn your project an ASP.NET Core project which targets only the full .NET 4.5.
You want/need to target .NET Core w/o working against the full .NET 4.5 Framework
This is a bit more difficult. You either need a replacement for the same library in .NET Core. If it uses the same namespaces, just add its references to the dnxcore50 moniker and you are good to go.
If there is no direct replacement, you have to remove this code parts from .NET Core projects, by using preprocessor directives.
#if DNX451
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
#endif
Now your namespace will be used only in the .NET 4.5 target, but not in the .NET Core target.
On a sidenote: You can remove the net451 moniker, as it's only used for Class Library (Package), the new project type for .NET Core libraries which compiles into a package which targets multiple framework targets. See the RC1 announcement for more.
For applications (ASP.NET Core Web Project or xUnit project) always use the application moniker (dnx451 and dnxcore50 respectively). For class libraries it's net451 and dotnet5.x.
To the anser of #Tseng I want to add that Directory Services are planned for .NET Core 1.2. Here is the feature request on GitHub: https://github.com/dotnet/corefx/issues/2089. You can subscribe there and get notifications when something is happening there!
When it's released you can just use Directory Services in ASP.NET Core with .NET Core! It might take some time, considering the current state and version of .NET Core, though.
Microsoft has released pre-release version for System.DirectoryServices in asp.net core 2.0. You can get it from nuget package manager using this command:
Install-Package System.DirectoryServices -Version 4.5.0-preview1-25914-04
This is working fine for me till now.
I'm trying to use System.IO.Compression.ZipArchive in a ASP.NET VNext class library in VS2015 Preview. I added the System.IO.Compression package using NuGet, and it added it to my project.json as a aspnetcore50 dependency.
When I try to use the ZipArchive, the intellisense says is not available in ASP.NET 5.0 but it is available in ASP.NET Core 5.0. If I switch to use ASP.NET Core using the drop down in the top bar, then my code works as expected, but when I choose normal ASP.NET it doesn't work.
I tried manually adding it as a dependency to aspnet50 in the project.json, but that didn't fix it.
I need to use the full CLR over the Core CLR as I need to load assemblies into the AppDomain at run time, and I believe this isn't supported in the Core CLR.
Please could someone explain what's going on here, maybe point me to some articles or blog posts, show me how to fix this.
Update:
I guess a better way or wording this is - the ZipArchive is not available in aspnet50, but it is available in aspnetcore50 when I add the System.IO.Compression NuGet package. Why is this?
They only way that I get the project to compile and work was doing the following in the project.json. I'm not too familiar with the compression library so I did not spend time trying to compress a file. Below you will a sample code that will compile with no issue.
{
"version": "1.0.0-*",
"dependencies": {
},
"frameworks": {
"aspnet50": {
"dependencies": {
},
"frameworkAssemblies": {
"System.IO.Compression": "4.0.0.0"
}
},
"aspnetcore50": {
"dependencies": {
"System.Runtime": "4.0.20-beta-22231",
"System.IO.Compression.ZipFile": "4.0.0-beta-22231",
"System.IO": "4.0.10-beta-22231",
"System.IO.FileSystem": "4.0.0-beta-22231"
}
}
}
}
Sample Code
public static void ZipFile(string path)
{
var data = new MemoryStream(File.ReadAllBytes(path));
var zip = new ZipArchive(data, ZipArchiveMode.Create,false);
zip.CreateEntry(path + ".zip");
}