System.MissingMethodException 单元测试

System.MissingMethodException Unit Test

Project References 在 Visual Studio 2017 Test Runner 中似乎存在运行时问题。单元测试 CSPROJ 使用 TargetFramework=net47 构建得很好,但在执行时我们从 MSTEST 或 XUNIT 收到以下消息。使用 Microsoft.NET.Test.Sdk v15.0.0.

测试执行错误 (x86):Serilog Seq 扩展

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)'.

单元测试示例 - Serilog

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

如果我们引用 net462 个项目,我们会得到相同的结果,因此我们认为它与 VS 2017 相关,而不是 .NET Framework 版本。我们从未在 VS 2015 中看到过此错误。似乎在使用可选参数/匹配签名等加载 DLL 扩展时出现问题。该方法显然存在或无法编译 - 为什么在运行时会崩溃?

如果我只使用本地 nuget 包,它工作正常 - 这似乎只是在 .NET Core CSPROJ 中通过 ProjectReference 引用任何项目时出现问题。它似乎没有正确处理依赖关系树。

使用 KeyVault 的另一个示例,其中 VS Test Runner 无法正确找到扩展方法...

测试执行错误 (x86):KeyVault 扩展

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

单元测试示例 - 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;
}

发现 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 这个奇怪的问题,哪个版本 15.0.0 掩盖了真正的问题。一旦我将 nuget 升级到 15.3.0-preview-20170502-03,就会出现不同的异常。

错误来源: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.'

这很有趣 - MissingMethodException 掩盖了隐藏在 System.Net.Http 中的真正问题。第二个认识是这个 base library has a bug which prevents the type from being loaded. Once I nuget updated System.Net.Http to version 4.3.1,问题消失了,我的项目引用又开始工作了。

结论

更新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.

选项 #2 - 排除包引用资产

对于最新的 VS 2017 CSPROJ 格式 - 以下配置也修复了此问题,因为它禁止将 System.Net.Http 复制到默认加载的 Build Output 路径GAC 的版本 4.0.0.0

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

选项 #3 - 程序集绑定重定向

dotnet 核心将遵循您在 app.config 中放置的任何运行时绑定重定向,因此您必须 System.Net.Http 到版本 4.1.* 的任何 nuget 依赖项,您可以重定向到最新版本或恢复到上一个​​稳定版本 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>

我在测试一个 class 项目时遇到了这个问题,该项目依赖于正在测试的项目中更新的 Nuget 包,但在测试项目中没有(这是缺失方法的来源)。

解决方案很简单,只需在测试项目中升级受影响的 Nuget:

Right-Click the test project > Manage Nuget packages > Upgrade necessary packages

我正在开发 SharePoint 插件,该插件已安装在我也用于开发的服务器上。因此,我认为该DLL在GAC中,并且该DLL首先被提取!

我从测试运行器那里得到了 MissingMethodException。所以我想出了一个简单的解决办法。

更改 AssemblyInfo.cs! 中的版本号 这将使 GAC 中的版本号与 bin/Release 目录中的版本号不同,因此测试运行程序将使用正确的 DLL。呸!

另请参阅:

System.MissingMethodException: Method not found?