.net 单元测试AppContext开关
更改日志.net 单元测试AppContext开关,.net,unit-testing,nunit,signedxml,cryptographicexception,.net,Unit Testing,Nunit,Signedxml,Cryptographicexception,更改日志 重命名的问题:AppContext开关在单元测试中失败(加密异常:指定的算法无效) 在做了更多调查后,在底部添加了一节,进一步详细解释了问题 在底部添加了一节,解释我已经实现的解决方法 我有一段代码,我正在为一些xml编写单元测试 在开发代码时,我注意到.NET 4.7.1+将抛出加密异常:指定的算法无效。为了解决这个问题,我使用了以下AppContext开关(来源:,) 我已将以下代码放入调用我的xml签名代码的任何应用程序中: AppContext.SetSwitch("Swi
- 重命名的问题:AppContext开关在单元测试中失败(加密异常:指定的算法无效)
- 在做了更多调查后,在底部添加了一节,进一步详细解释了问题
- 在底部添加了一节,解释我已经实现的解决方法
加密异常:指定的算法无效
。为了解决这个问题,我使用了以下AppContext
开关(来源:,)
我已将以下代码放入调用我的xml签名代码的任何应用程序中:
AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);
AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
在野外运行时,此代码运行正常,并且我的xml按预期进行了签名
我已经为这段代码编写了一些单元测试,这是我第一次真正尝试编写单元测试,我遇到了一些奇怪的边缘案例
try
{
// Compute the signature.
signedXml.ComputeSignature();
}
catch (CryptographicException cex)
{
//Contains instead of == since this message contains newline characters...
if (cex.Message.Contains("Invalid algorithm specified"))
{
string code = Environment.NewLine + "AppContext.SetSwitch(\"Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms\", true);" +
Environment.NewLine + "AppContext.SetSwitch(\"Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms\", true); ";
throw new Exception($"Cryptographic exception was thrown, ensure that the following switches are set in the executing assembly: {code}", cex);
}
else
{
throw cex;
}
}
因此,如果抛出异常,我会显示一条很好的消息,说请在调用此方法之前添加以下代码
我的测试类如下所示:
[TestFixture]
public class XMLSigningTests
{
protected IXMLSigner _xmlSigner;
protected byte[] _publicKey;
protected string _password;
[SetUp]
public void Init()
{
_xmlSigner = new XMLSigner();
_password = "test";
_publicKey = GenerateTestCert(_password);
}
[TearDown]
public void CleanUp()
{
_xmlSigner = null;
_publicKey = null;
_password = null;
}
[Test]
public void SignXML_AppContextSwitchNotSet_Fail()
{
XMLDocument xmlDoc = GenerateXML();
Assert.Throws<Exception>(() => { _xmlSigner.SignXML(xmlDoc, _publicKey, _password); });
}
[Test]
public void SignXML_AppContextSwitchSet_Success()
{
AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);
AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
XMLDocument xmlDoc = GenerateXML();
var signedXml = _xmlSigner.SignXML(xmlDoc, _publicKey, _password);
Assert.IsFalse(signedXML == null);
//More validation here
}
private XMLDocument GenerateXML()
{
return new XMLDocument("Some fancy xml here...");
}
private byte[] GenerateTestCert(string password)
{
//Use Pluralsight.Crypto to generate a self signed cert & export as .pfx
return cert.Export(X509ContentType.Pfx, password);
}
}
现在,您希望这段代码通过我的失败测试(没有设置开关),它确实通过了,您可以在测试资源管理器中看到我的原始NotImplementedException
消息。然而,我期望成功的测试再次抛出加密异常
System.Exception : Cryptographic exception was thrown, ensure that the following switches are set in the executing assembly:
AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);
AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
----> System.Security.Cryptography.CryptographicException : Invalid algorithm specified.
正如我之前所说的,我对测试非常陌生,我不确定我的测试设计方法是否错误,如果我只是在测试一些隐藏的意大利面代码,那么也许我注定要尝试测试它,或者我遗漏了一些东西来正确测试这个案例
我目前正在使用NUnit 3.12.0+NUnit3TestAdapter 3.15.1
编写测试,尽管我最初使用的是MSTest 1.3.2
,并且在使用这两个框架时经历了相同的行为
更新 我发现以下测试的执行顺序决定了成功:
- SignXML\u AppContextSwitchNotSet\u失败
- SignXML\u AppContextSwitchSet\u成功
//Test I expect to fail
AppContext.SetSwitch("the switch..", false);
//Test I expect to pass
AppContext.SetSwitch("the switch..", true);
尽管我已经测试了这些值是否设置正确,但底层交换机是否正在更新?如何清理这些底层对象
解决方案/讨厌的修复 我在上发现了以下问题。在这个线程中,他们讨论了每个测试中新的
AppDomain
选项,这正是我的案例中需要的
下面的一个线程发布了一个util类,在一个单独的AppDomain
()中运行代码(我不会在这里发布,因为这篇文章已经很庞大了)。我使用了这个util类并调整了测试以使用它(您不能使用任何类变量或方法,这意味着我必须复制我的helper方法代码)
一旦我实现了util并调整了我的测试以符合它的标准,当我单独运行它们时,测试就开始通过这两个测试&一次全部通过
任务完成了 我也有同样的问题! 我偶然发现了这篇文章,它激发了我的解决方案 我没有在单独的AppDomain中运行测试,而是修改了调用加密库的生产代码。 我在一个单独的AppDomain中运行有问题的调用,在继续之前在其中设置开关 这修复了所有的测试,并且使我的库的客户端不会弄乱开关
//Test I expect to fail
AppContext.SetSwitch("the switch..", false);
//Test I expect to pass
AppContext.SetSwitch("the switch..", true);