如何忽略单元测试中的程序集引用不匹配?

How do I ignore the assembly reference mismatch in unit tests?

我正在尝试篡改程序集,以便能够模拟不容易被模拟的代码,such as SharePoint assemblies

作为原型,我有一个解决方案,其中测试代码通过使用 ILRepack 和 Mono.Cecil 的自定义构建操作被篡改,因此实际代码不是最初编写的代码。

当包含测试代码的程序集未签名时,一切正常。签署程序集后,我看到了预期的错误:

The located assembly's manifest definition does not match the assembly reference.

由于程序集被篡改,显然,密钥不相同(如果在篡改后签名)或不存在。

我认为通过 AppDomain.CurrentDomain.AssemblyResolve 事件可以强制接受被篡改的程序集,但事实并非如此。

我如何要求 .NET Framework 在完全信任的单元测试 运行 期间忽略程序集匹配检查,并在它期望对它们进行签名时接受未签名的程序集?


据我了解,问题不在于强名称验证。不仅错误会有所不同,而且 running the corresponding sn –Vr 也没有效果:错误仍然存​​在。

实际问题似乎出在程序集绑定级别。这也是为什么我惊讶地看到引发了 AppDomain.CurrentDomain.AssemblyResolve 事件,但它的结果仍然被忽略;可能,它并没有像我一直认为的那样。

解决方案比我想象的要简单得多。正如我所猜测的那样,问题不在于强名称验证,而是依赖于 public 密钥令牌的程序集绑定,因此可以在篡改程序集时替换令牌。

第一步是在篡改之前,获取原始public密钥和public密钥令牌。它们都在 AssemblyName.

var originalAssemblyBytes = File.ReadAllBytes(originalFilePath);
var originalAssemblyName = Assembly.Load(originalAssemblyBytes).GetName();

下一步是篡改本身:首先使用 ILRepack 合并两个程序集,然后使用 Mono.Cecil 进行更精细的更改。在第二步中,Mono.Cecil 用于替换 public 密钥和 public 密钥令牌:

var assemblyName = mergedModule.Assembly.Name;
assemblyName.HasPublicKey = true;
assemblyName.PublicKey = originalAssemblyName.GetPublicKey();
assemblyName.PublicKeyToken = originalAssemblyName.GetPublicKeyToken();

必须同时更改两者:如果仅更改令牌,则一旦使用程序集就会抛出“无效程序集public密钥”错误。

这适用于使用 .snk 和 .pfx 签名的两个程序集:因为测试是 运行 完全信任的,所以验证没有完成,这意味着 public 密钥没有'对应私钥无关