Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.4 is not working with Fakes #3003

Closed
Evangelink opened this issue May 28, 2024 · 25 comments
Closed

3.4 is not working with Fakes #3003

Evangelink opened this issue May 28, 2024 · 25 comments

Comments

@Evangelink
Copy link
Member

3.4.0 and 3.4.1 are both not working while 3.3.1 was fine for this scenario:

  • .NET8 ProjectX
  • .NET8 test ProjectY which uses Microsoft Fakes for project X
  • Build on Azure DevOps using VSBuild@1.
  • Run ProjectY

The Fakes assemblies cannot be resolved, each test that uses them outputs:

System.IO.FileNotFoundException: Could not load file or assembly 'ProjectX.Fakes, Version=x.x.x.x, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified..

Where ProjectX.Fakes.dll is present in the output folder next to ProjectY.exe.

Originally posted by @Rans4ckeR in #2922 (comment)

@Evangelink
Copy link
Member Author

Could you please provide some more details? Are you using VSTest or MSTest runner to run the tests? Is the issue happening only on VS? Would it be possible for you to create a small reproducer?

cc @drognanar @jakubch1

@Rans4ckeR
Copy link

Could you please provide some more details? Are you using VSTest or MSTest runner to run the tests? Is the issue happening only on VS? Would it be possible for you to create a small reproducer?

cc @drognanar @jakubch1

I can only reproduce it on Azure DevOps, not locally;

Pipeline bits

pool:
  vmImage: 'windows-2022'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  Agent.Source.Git.ShallowFetchDepth: 0

steps:
- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '8.x'

- task: VSBuild@1
  displayName: 'Build Solution'
  inputs:
    solution: '$(solution)'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
    maximumCpuCount: true
    msbuildArchitecture: 'x64'

- task: CmdLine@2
  displayName: 'Run tests'
  inputs:
    script: '.\TestProject\bin\Release\net8.0\TestProject.exe --report-trx --coverage'

ProjectX

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>
  <ItemGroup>
    <InternalsVisibleTo Include="TestProject" />
    <InternalsVisibleTo Include="ProjectX.Fakes" />
  </ItemGroup>
</Project>

TestProject

<Project Sdk="MSTest.Sdk/3.4.1">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>
  <ItemGroup>
    <Compile Remove="FakesAssemblies\**" />
    <EmbeddedResource Remove="FakesAssemblies\**" />
    <None Remove="FakesAssemblies\**" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.QualityTools.Testing.Fakes" Version="17.5.0-beta.23060.1" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\ProjectX\ProjectX.csproj" />
  </ItemGroup>
  <ItemGroup>
    <AdditionalDesignTimeBuildInput Remove="FakesAssemblies\**" />
  </ItemGroup>
</Project>

TestProject\Fakes\ProjectX.fakes

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="ProjectX"/>
  <StubGeneration>
    <Clear/>
    <Add Interfaces="true" Namespace="ProjectX!"/>
  </StubGeneration>
  <ShimGeneration Disable="true"/>
</Fakes>

If I build & run the tests locally in VS it works. Both running the tests in VS and running the .exe directly works.
If I copy the binaries produced from the pipeline to my local machine I get the same assembly resolution error.

Also tried this in the pipeline with the same result:

  • Use dotnet test instead of running the .exe
  • Downgrading Microsoft.QualityTools.Testing.Fakes to the latest stable
  • Target .NET9 instead of .NET8

@drognanar
Copy link
Member

what's the VS version on your local machine vs your CI? we recently updated the MSBuild props/targets files to include the Fakes dependencies in the executable's runtime configuration

with older VS versions, assembly resolution only works via vstest.console.exe, because it has a custom assembly resolver and picks up the Fakes assemblies regardless of the runtime configuration file content.

@Rans4ckeR
Copy link

what's the VS version on your local machine vs your CI? we recently updated the MSBuild props/targets files to include the Fakes dependencies in the executable's runtime configuration

with older VS versions, assembly resolution only works via vstest.console.exe, because it has a custom assembly resolver and picks up the Fakes assemblies regardless of the runtime configuration file content.

On local machine 1 I have Microsoft Visual Studio Enterprise 2022 (64-bit) - Current Version 17.10.0
On local machine 2 I have Microsoft Visual Studio Enterprise 2022 (64-bit) - Preview Version 17.11.0 Preview 1.0
The CI machine, at the time of writing, has Visual Studio Enterprise 2022 | 17.9.34902.65

So it is expected that Fakes with 3.4.x does not work with VS <17.10 unless using VSTest@2?

@drognanar
Copy link
Member

Yes, that's expected.

You'd need to have a custom assembly resolver to resolve the dlls from .exe's folder without the correct runtime configuration.

@Rans4ckeR
Copy link

Yes, that's expected.

You'd need to have a custom assembly resolver to resolve the dlls from .exe's folder without the correct runtime configuration.

So it's an undocumented breaking change, since 3.3.1 works fine?

@drognanar
Copy link
Member

if it's been working via a .exe already then there must be a change in how MSTest itself resolves assemblies

@Evangelink are you aware of any changes to assembly resolution in MSTest?

@Evangelink
Copy link
Member Author

Outside of the bugs of 3.4.0 where the resolver wasn't triggered or the infinite recursion with resources not that I am aware of.

@cbersch
Copy link

cbersch commented May 29, 2024

Outside of the bugs of 3.4.0 where the resolver wasn't triggered or the infinite recursion with resources not that I am aware of.

@Evangelink What infinite recursion with resources are you referring to? I couldn't find any related bug.
We are expiriencing a problem on Azure DevOps with

The active test run was aborted. Reason: Test host process crashed : Process terminated. Encountered infinite recursion while looking up resource 'Arg_NullReferenceException' in System.Private.CoreLib. Verify the installation of .NET is complete and does not need repairing, and that the state of the process has not become corrupted.

Both with MSTest 3.3.1 and 3.4.0. However I cannot directly relate it to MSTest

@Evangelink
Copy link
Member Author

@Evangelink What infinite recursion with resources are you referring to? I couldn't find any related bug.

I am referring to #2692.

The active test run was aborted. Reason: Test host process crashed : Process terminated. Encountered infinite recursion while looking up resource 'Arg_NullReferenceException' in System.Private.CoreLib. Verify the installation of .NET is complete and does not need repairing, and that the state of the process has not become corrupted.

Could you please provide either a repro or diagnostic logs (see https://github.com/microsoft/vstest/blob/main/docs/diagnose.md)

@cbersch
Copy link

cbersch commented May 29, 2024

@Evangelink What infinite recursion with resources are you referring to? I couldn't find any related bug.

I am referring to #2692.

Ok, that is a different one.

The active test run was aborted. Reason: Test host process crashed : Process terminated. Encountered infinite recursion while looking up resource 'Arg_NullReferenceException' in System.Private.CoreLib. Verify the installation of .NET is complete and does not need repairing, and that the state of the process has not become corrupted.

Could you please provide either a repro or diagnostic logs (see https://github.com/microsoft/vstest/blob/main/docs/diagnose.md)

If I can reproduce it reliably, I'll create an issue. Thanks.

@Evangelink
Copy link
Member Author

Awesome, thank you @cbersch

@Rans4ckeR
Copy link

So it is expected that Fakes with 3.4.x does not work with VS <17.10 unless using VSTest@2?

Yes, that's expected.

You'd need to have a custom assembly resolver to resolve the dlls from .exe's folder without the correct runtime configuration.

VS was updated to 17.10 by actions/runner-images#9965 but I still see an 'invalid' .exe being generated with 3.4.1 which can't resolve the Fakes assemblies.

if it's been working via a .exe already then there must be a change in how MSTest itself resolves assemblies

@Evangelink are you aware of any changes to assembly resolution in MSTest?

The .exe generated by 3.3.1 works fine on Azure DevOps with VS 17.10.

@Evangelink
Copy link
Member Author

ping @drognanar

@drognanar
Copy link
Member

I just pushed a new package https://www.nuget.org/packages/Microsoft.Testing.Extensions.Fakes that should support Fakes and the new MSTest runner working side by side.

If you replace the existing Microsoft.QualityTools.Testing.Fakes package reference with the new extension reference it will pick up all of the environment variables as well as add the relevant instrumentation files to the bin folder to ensure that shims can be executed.

@Rans4ckeR
Copy link

I just pushed a new package https://www.nuget.org/packages/Microsoft.Testing.Extensions.Fakes that should support Fakes and the new MSTest runner working side by side.

If you replace the existing Microsoft.QualityTools.Testing.Fakes package reference with the new extension reference it will pick up all of the environment variables as well as add the relevant instrumentation files to the bin folder to ensure that shims can be executed.

I think you forgot to push the dependency Microsoft.QualityTools.Testing.Fakes (>= 17.11.0-beta.24318.5)?

@drognanar
Copy link
Member

Thanks for letting me know.
Working on it right now, I need to update the version of the Microsoft.Testing.Platform that the package depends on as well. This requires building new packages.

Will update on the thread, once new packages are built and published.

@drognanar
Copy link
Member

Updated both of the packages

@Rans4ckeR
Copy link

Updated both of the packages

The result seems to be the same with MSTest.Sdk/3.4.3 and Microsoft.Testing.Extensions.Fakes 17.11.0-beta.24319.3:

Unable to create instance of class TestClassY. Error: System.IO.FileNotFoundException: Could not load file or assembly 'XXX.Fakes, Version=x.x.x.x, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified..
Stack Trace:
at TestClassY..ctor()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

MSTest.Sdk/3.3.1 and Microsoft.Testing.Extensions.Fakes 17.11.0-beta.24319.3 works fine.

Are you perhaps able to spin up an Azure DevOps build yourself and reproduce it?

@drognanar
Copy link
Member

I rolled back the targets file change locally and was able to reproduce it.

By bisecting the MSTest repo, the first package where this behaviour changed is this one #2654, so I'll let @Evangelink take a further look

@drognanar drognanar assigned Evangelink and unassigned drognanar Jun 19, 2024
@Evangelink
Copy link
Member Author

@Rans4ckeR could you please confirm that when using a more recent version of VS the extension is working fine?

@Rans4ckeR
Copy link

@Rans4ckeR could you please confirm that when using a more recent version of VS the extension is working fine?

When locally using VS 17.10 or VS 17.11 everything always works, regardless of the versions of any of the packages involved. Tests are running fine inside VS and tests are running fine when using the compiled .exe.

When compiling on Azure DevOps using VSBuild@1 the compiled .exe has different assembly probing logic than the one compiled locally. Only when reverting to MSTest.Sdk/3.3.1 the Azure DevOps .exe uses correct assembly probing.

The current runners on Azure DevOps are using VS 17.10.

The difference might be that VSBuild@1 is using MSBuild.exe while locally dotnet.exe is always used or something?

@Evangelink
Copy link
Member Author

The difference might be that VSBuild@1 is using MSBuild.exe while locally dotnet.exe is always used or something?

I guess the difference is the version of MSBuild being inserted/available in dotnet SDK compared to the one in VS.

For the change in the version of MSTest. We introduced support of assembly resolution for .NET Core in #2110 but received many bugs related to this new feature as it's impacting how assemblies are being resolved by .NET so we decided to only plug the assembly resolver (for .NET Core) when user is asking for AssemblyResolution support in the .runsettings. This means that you ended up in the happy path of fakes working with MSTest 3.3 thanks to the assembly resolver although it wasn't designed for it. On MSTest 3.4+, we have this logic of using the resolver only when needed.

You will either need to wait for AzDO to contain the correct preview version of VS that contains the fix (@drognanar could you please confirm the version) or you will need to use AssemblyResolution functionality (https://learn.microsoft.com/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file#mstest-element) pointing to your bin folder.

@drognanar
Copy link
Member

The Fakes changes that makes Fakes assemblies load even without a custom assembly loader
have been merged in 17.11-preview 1.

@Evangelink
Copy link
Member Author

Closing the issue as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants