I am working on migrating .NET 4.x code onto .NET 5. The unit test projects make extensive use of of Microsoft Fakes, which recently gained an official implementation for .NET 5 with Visual Studio 2019. I have the build and unit tests running locally and started setting up a CI/CD pipeline for the project in AzureDevOps (On Prem ). I have VS 2019 Enterprise installed locally and on the build agent server
My build pipeline consists of a dotnet restore
with the following options
-s https://api.nuget.org/v3/index.json -s "C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\"
I've included the "C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\"
as a source since I have determined that Microsoft fakes is local nuget package that gets installed by VS 2019 enterprise edition in this specific directory.
After the restore are two dotnet build
commands run with the following options
--no-restore --configuration $(BuildConfiguration) /p:VersionPrefix=$(Build.BuildNumber) /p:AssemblyVersion=$(Build.BuildNumber) /p:GenerateProjectSpecificOutputFolder=True
I'm using 2 dotnet build
commands because I noticed that the way I had the task set up using one command was causing the Test projects to be built before the project they were testing and didn't want to spend time on finding a glob pattern to set the the build order correctly. (Or I was misreading the logs, either way I split it out for clarity while debugging)
When the dotnet build
command runs for the test project, it fails with the message The type or namespace name 'Fakes' does not exist in the namespace (are you missing an assembly reference?)
. This tells me that the Fakes assemblies I have in the test projects are not getting generated by dotnet build
(or at least with the options I have currently). What do I need to do in order to generate the Fakes assemblies?
Misc: I am using the 1.x version of the .NET CORE task in azure dev ops.
After a suggestion in another forum, running the relevant dotnet
commands on my local workstation also produced the same error. At the request of another Here is a breakdown
dotnet build .sln --configuration Debug /p:GenerateProjectSpecificOutputFolder=True
worked locally, but I realized that I still had the fakes assemblies from the last time I built the sln in Visual Studio. So then tried
dotnet clean
dotnet build .sln --configuration Debug /p:GenerateProjectSpecificOutputFolder=True
which errored out with the Fakes does not exist
error. I then tried
dotnet clean
dotnet build Main.csproj --configuration Debug /p:GenerateProjectSpecificOutputFolder=True
dotnet build Main.Tests.csproj --configuration Debug /p:GenerateProjectSpecificOutputFolder=True
The build of Main.csproj was successful while the build of Main.Tests.csproj errored out with Fakes does not exist
dotnet clean
dotnet restore
dotnet build .sln --configuration Debug --no-restore /p:GenerateProjectSpecificOutputFolder=True
also gives the Fakes does not exist
error
according to dotnet nuget list source
I am pulling packages from the following sources
1. nuget.org [Enabled]
https://api.nuget.org/v3/index.json
2. <Internal Nuget Feed 1> [Enabled]
<Details Redacted>
3. DevExpress 19.1 Local [Enabled]
C:\Program Files (x86)\DevExpress 19.1\Components\System\Components\Packages
4. Microsoft Visual Studio Offline Packages [Enabled]
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
5. <Internal Nuget Feed 2> [Enabled]
<Details Redacted>
After re-reading some of the MS docs regarding fakes that more times than I care to admit, I finally found the main cause of my problem. According to this page in the section for Using Microsoft Fakes in the CI
which says in the very first paragraph
Since Microsoft Fakes requires Visual Studio Enterprise, the generation of Fakes Assemblies requires that you build your project using Visual Studio Build Task.
I also found that this also applies for running the unit tests where you consume Microsoft Fakes. You cannot use dotnet test
in the pipeline and instead need to use a Visual Studio Test
task.
Both of these tasks must use Visual Studio 2019 or later. This was complicated in my case since we are using TFS 2017 which will not detect Visual Studio 2019 in either of these pipeline tasks, even when you choose Latest
as the Visual Studio version.
To get around this, I had to change Visual Studio Build
to using an MS Build
task in order to point to the MS build from the 2019 install. For the unit tests, I had to write a custom powershell script to call the correct version of vstest.console.exe
. Later versions of the Visual Studio Test
task added a field to change this path so you don't have to use a PowerShell Script.
If you need help finding the paths to msbuild.exe and vstest.console.exe, you can open Visual Studio 2019 Developer Prompt on the build server and run
where msbuild
and where vstest.console.exe
to get the paths you would need to use in your pipeline.
For publishing, you can still use dotnet publish
if you add the --no-build
argument. You will also need to exclude projects with the pattern !**/f.csproj
from the publish command if you are using a wildcard pattern like **/*.csproj
with it. the f.csproj
files are from fakes generation during the build, and the publish task will error if it finds them with messages similar to
Could not copy the file "obj\Debug\net5.0\Fakes\sdc\b\net5.0\System.Data.Common.5.0.0.0.Fakes.deps.json" because it was not found. [obj\Debug\net5.0\Fakes\sdc\f.csproj]