You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python单元测试模拟X509证书遇PEM报错,求解决方案

单元测试模拟证书读取时OpenSSL.crypto.Error问题的解决方法

原函数代码

def get_private_key():
    with open(config.CERTIFICATE_PATH + config.PRIVATE_KEY, 'rb') as key_file, \
             open(config.CERTIFICATE_PATH + config.PUBLIC_KEY, 'rb') as cert_file_string:
        private_key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend())
        cert = load_certificate(FILETYPE_PEM, cert_file_string.read())
    sha1_fingerprint = cert.digest("sha1")
    strkid = sha1_fingerprint.decode()
    kid = strkid.replace(':', '')

测试代码及错误

测试代码:

@patch('OpenSSL.crypto.load_certificate')
@patch('cryptography.hazmat.primitives.serialization.load_pem_private_key')
@patch('builtins.open')
def test_get_private_key(self, mock_open, mock_load_pem_private_key, mock_load_certificate)
    mock_open.return_value = io.BytesIO('dummy'.encode('utf-8'))
    mock_load_pem_private_key.return_value = MagicMock(cryptography.hazmat.backends.openssl.rsa.RSAPrivateKey)
    mock_load_certificate.return_value = MagicMock(crypto.X509)
    self.assertEqual(get_private_key(), "dummyPvtKey")

运行时错误:

OpenSSL.crypto.Error: [('PEM routines', 'get_name', 'no start line')]


问题原因及解决步骤

1. 修正patch路径(核心问题)

错误出现的根本原因是patch的目标路径不正确:你需要patch的是被测试函数所在模块中实际导入的load_certificate对象,而非原始的OpenSSL.crypto.load_certificate。

  • 假设get_private_key位于your_project.auth.utils模块,且该模块中导入语句为from OpenSSL.crypto import load_certificate,则测试中的patch应改为:
    @patch('your_project.auth.utils.load_certificate')
    
  • 如果模块中是import OpenSSL.crypto并通过OpenSSL.crypto.load_certificate调用,则patch路径应为your_project.auth.utils.OpenSSL.crypto.load_certificate

2. 修复多文件打开的mock逻辑

原测试中mock_open.return_value只返回一个BytesIO实例,但函数同时打开了两个文件(私钥和证书),需要让mock_open按顺序返回不同的模拟内容:

mock_open.side_effect = [
    io.BytesIO(b'-----BEGIN PRIVATE KEY-----\ndummy_key_content\n-----END PRIVATE KEY-----'),
    io.BytesIO(b'-----BEGIN CERTIFICATE-----\ndummy_cert_content\n-----END CERTIFICATE-----')
]

这样即使patch未完全生效,也能避免因内容不符合PEM格式触发解析错误。

3. 完善mock对象的方法返回值

原函数最终返回的是证书SHA1指纹去除冒号后的字符串,需要让mock的证书对象返回符合预期的digest结果:

# 模拟证书对象的digest方法返回值
mock_cert = MagicMock()
mock_cert.digest.return_value = b'12:34:56:78'
mock_load_certificate.return_value = mock_cert

# 对应修改断言
self.assertEqual(get_private_key(), "12345678")

4. 修复测试函数的语法错误

原测试函数定义末尾缺少冒号,修正为:

def test_get_private_key(self, mock_open, mock_load_pem_private_key, mock_load_certificate):

内容的提问来源于stack exchange,提问作者Ahmad Shaikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:36:19