System.MissingMethodException Unit Test
Asked Answered
K

3

9

Having what appears to be runtime issues with Project References in Visual Studio 2017 Test Runner. The Unit Test CSPROJ builds just fine with TargetFramework=net47, but at execution time we get the following message from MSTEST or XUNIT. Using Microsoft.NET.Test.Sdk v15.0.0.

Test Execution Error (x86): Serilog Seq Extension

System.MissingMethodException : Method not found: 'Serilog.LoggerConfiguration Serilog.SeqLoggerConfigurationExtensions.Seq(Serilog.Configuration.LoggerSinkConfiguration, System.String, Serilog.Events.LogEventLevel, Int32, System.Nullable1<System.TimeSpan>, System.String, System.String, System.Nullable1, System.Nullable1<Int64>, Serilog.Core.LoggingLevelSwitch, System.Net.Http.HttpMessageHandler, System.Nullable1, Boolean, Int32)'.

Unit Test Example - Serilog

[Fact]
public void TestMethod1()
{
    LoggerConfiguration loggerConfig = new LoggerConfiguration();    
    loggerConfig.MinimumLevel.Debug();                    
    loggerConfig.WriteTo.LiterateConsole();    
    loggerConfig.WriteTo.Seq("http://localhost:65454");    
}

If we reference net462 projects, we get the same result so we believe it is related to VS 2017, not .NET Framework version. We have never seen this error with VS 2015. Seems like there is an issue loading DLL extensions with optional parameters / matching signatures, etc. The method clearly exists or it wouldn't compile - why at runtime is this crashing out?

If I just use local nuget packages it works fine - this only seems to be a problem when referencing any Projects via ProjectReference in .NET Core CSPROJ. It doesn't seem to handle the dependency tree properly.

Another example using KeyVault where VS Test Runner cannot find the extension methods properly...

Test Execution Error (x86): KeyVault Extension

Message: System.MissingMethodException : Method not found: 'Void Microsoft.Azure.KeyVault.KeyVaultClient..ctor(AuthenticationCallback, System.Net.Http.DelegatingHandler[])'.

Unit Test Example - KeyVault

[Fact]
public void TestMethod1()
{
    KeyVaultClient _kvClient = new KeyVaultClient(new AuthenticationCallback(getKeyVaultToken));
}

private static async Task<string> getKeyVaultToken(string authority, string resource, string scope)
{
    var authContext = new AuthenticationContext(authority);
    ClientCredential clientCred = new ClientCredential("test", "account");
    AuthenticationResult result = authContext.AcquireTokenAsync(resource, clientCred).Result;

    if (result == null)
        throw new InvalidOperationException("Failed to obtain the JWT token");

    return result.AccessToken;
}
Karttikeya answered 9/5, 2017 at 15:29 Comment(0)
K
14

Discovered this odd issue with dotnet test is two-fold. After running dotnet test --diag and reviewing the output, it led me to realize there are newer releases of Microsoft.NET.Test.Sdk which version 15.0.0 was masking the real problem. Once I upgraded the nuget to 15.3.0-preview-20170502-03, a different exception appeared.

Error Source: Microsoft.Rest.ClientRuntime

System.TypeLoadException: 'Inheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'. Derived types must either match the security accessibility of the base type or be less accessible.'

Now this is interesting - the MissingMethodException was masking the real problem which was buried in System.Net.Http. The second realization is that this base library has a bug which prevents the type from being loaded. Once I nuget updated System.Net.Http to version 4.3.1, the issue went away and my Project References started working again.

Conclusion

Update Microsoft.NET.Test.SDK to latest preview and System.Net.Http to latest version to get past the weird MissingMethodException with dotnet test. You can track the open issue on github here.

Option #2 - Excluding Package Reference Assets

For latest VS 2017 CSPROJ formats - the following config also fixes this as it supresses copying System.Net.Http to the Build Output path which by default loads the GAC'd version 4.0.0.0.

<PackageReference Include="System.Net.Http" Version="4.3.1">
  <ExcludeAssets>All</ExcludeAssets>
</PackageReference>

Option #3 - Assembly Binding Redirect

dotnet core will follow any runtime binding redirects you place in your app.config, so any nuget dependencies you have to System.Net.Http to version 4.1.*, you can redirect to the latest version or revert to the last stable version 4.0.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <!-- Another PackageReference dependency binds to 4.1.1 which is busted, we leverage .NET Core redirection and revert to CLR 4.0.0 -->
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="4.0.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
Karttikeya answered 9/5, 2017 at 16:12 Comment(3)
Had this same issue MissingMethodException in powershell...turns out that if you downgrade System.Net.Http to target version 4.0.0.0 (GAC'd) it will revert the security issue in newer versions.Karttikeya
System.MissingMethodException was failing my unit tests in .NetFramework project only on Windows machine, on Mac they passed perfectly. Adding a reference to a Microsoft.NET.Test.SDK packaged had solved the issue for me.Velda
Just spent a day trying to figure out the same problem with Azure Key Vault failing with missing method exception for the constructor when running a unit test with VS Test Explorer - thanks!Achromat
O
0

I encountered this issue while testing a class from a project that had a dependency on a Nuget package that had been updated in the project being tested, but not in the test project (which was the source for the missing method).

The solution was as simple as upgrading the affected Nuget in the test project:

Right-Click the test project > Manage Nuget packages > Upgrade necessary packages
Omphalos answered 23/3, 2021 at 15:19 Comment(0)
B
0

I am working on a SharePoint plug-in and the plug-in has been installed on the server that I am also using to do development. Therefore, I think the DLL is in the GAC and that DLL is being picked up first!

I was getting the MissingMethodException from the test runner. So I came up with an easy fix.

Change the version number in AssemblyInfo.cs! This will make the version number in the GAC and the one in your bin/Release directory different, so the test runner will use the correct DLL. Phew!

See also:

System.MissingMethodException: Method not found?

Bouilli answered 22/12, 2021 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.