如何在XUnit测试中处理X509Certificate2?

huangapple go评论94阅读模式
英文:

How do I deal with X509Certificate2 in XUnit tests?

问题

我正在为我的应用程序编写 XUnit 测试,并且需要处理 X509Certificates。我面临的挑战是在 .NET 中无法创建 X509Certificate2 的模拟对象。因此,我正在探索替代方法,以在我的测试环境中有效地处理 X509Certificates。

我考虑过构建一个围绕 X509Certificate2 的包装器,或者使用类似 Certes、CertificateManager 或 BouncyCastle 的库。我的目标是找到一个在简单性、性能和可维护性之间取得平衡的解决方案。

为了让你更好地了解,这是我考虑的包装器的示例:

public interface ICertificate : IDisposable
{
    string Subject { get; }
    string Thumbprint { get; }
    DateTime NotBefore { get; }
    DateTime NotAfter { get; }
    
    X509Certificate2 Export();
}

public class Certificate : ICertificate
{
    private readonly X509Certificate2 _certificate;

    public Certificate(byte[] rawData)
    {
        _certificate = new X509Certificate2(rawData);
    }

    public string Subject => _certificate.Subject;
    public string Thumbprint => _certificate.Thumbprint;
    public DateTime NotBefore => _certificate.NotBefore;
    public DateTime NotAfter => _certificate.NotAfter;

    public X509Certificate2 Export()
    {
        return new X509Certificate2(_certificate);
    }

    public void Dispose()
    {
        _certificate.Dispose();
    }
}

考虑到无法模拟 X509Certificate2 的限制,我倾向于构建这个包装器。然而,我不确定是否这是最佳方法,或者是否利用其中提到的库(Certes、CertificateManager 或 BouncyCastle)会是更明智的选择。

如果你有关于如何高效处理 X509Certificates 的 XUnit 测试的经验或见解,我将非常感激你的建议。此外,如果每种方法都应该注意的优缺点,请分享。非常感谢你提前的帮助!

英文:

I'm working on writing XUnit tests for my application, and I need to deal with X509Certificates. The challenge I'm facing is that it's not possible to create a mock of the X509Certificate2 in .NET. As a result, I'm exploring alternative approaches to effectively handle X509Certificates in my test environment.

I have considered building a wrapper around X509Certificate2 or using libraries like Certes, CertificateManager, or BouncyCastle. My goal is to find a solution that strikes a balance between simplicity, performance, and maintainability.

To give you a better idea, here's an example of the wrapper I'm considering:

public interface ICertificate : IDisposable
{
    string Subject { get; }
    string Thumbprint { get; }
    DateTime NotBefore { get; }
    DateTime NotAfter { get; }
    
    X509Certificate2 Export();
}

public class Certificate : ICertificate
{
    private readonly X509Certificate2 _certificate;

    public Certificate(byte[] rawData)
    {
        _certificate = new X509Certificate2(rawData);
    }

    public string Subject => _certificate.Subject;
    public string Thumbprint => _certificate.Thumbprint;
    public DateTime NotBefore => _certificate.NotBefore;
    public DateTime NotAfter => _certificate.NotAfter;

    public X509Certificate2 Export()
    {
        return new X509Certificate2(_certificate);
    }

    public void Dispose()
    {
        _certificate.Dispose();
    }
}

Given the limitations of mocking X509Certificate2, I am leaning towards building this wrapper. However, I'm unsure if it's the best approach or if utilizing one of the mentioned libraries (Certes, CertificateManager, or BouncyCastle) would be a smarter choice.

If you have experience or insights regarding how to deal with X509Certificates in XUnit tests efficiently, I would greatly appreciate your advice. Additionally, if there are any pros and cons I should be aware of for each approach, please share them. Thank you in advance for your help!

答案1

得分: 1

解决此问题的一种方法如下:

首先,使用 makecert 生成一个证书。
将证书添加到项目(app_data 等)中,然后将构建操作更改为嵌入资源。

最后,按照以下方式加载证书:

byte[] 本地证书;
Assembly 此程序集 = Assembly.GetAssembly(typeof(MyType));
using (Stream 证书流 = 此程序集.GetManifestResourceStream("YourProjectName.localhost.pfx"))
{
  本地证书 = new byte[证书流.Length];
  证书流.Read(本地证书, 0, (int)证书流.Length);
}

_signingCert = new X509Certificate2(本地证书, "password");

这将为您提供一个本地证书,您可以使用它来编写单元测试。

英文:

One way to resolve the issue can be done by the following:

First, generate a certificate using makecert.
Add the certificate to the project (app_data etc.) and then change Build Action to Embedded Resource.

Finally, load the certificate like below:

byte[] localCertificate;
Assembly thisAssembly = Assembly.GetAssembly(typeof(MyType));
using (Stream certStream = thisAssembly.GetManifestResourceStream("YourProjectName.localhost.pfx"))
{
  localCertificate = new byte[certStream.Length];
  certStream.Read(embeddedCert, 0, (int)certStream.Length);
}

_signingCert = new X509Certificate2(localCertificate, "password");

This will give you a local certificate and can use it to write unit tests.

huangapple
  • 本文由 发表于 2023年6月8日 12:55:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76428722.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定