Search code examples
c#visual-studio-2019.net-5microsoft-fakes

Generate Microsoft Fakes assemblies in .NET 5


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.

Update 1

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>

Solution

  • 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]