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

如何Mock Fernet.decrypt以实现Python脚本测试覆盖?

解决Fernet解密测试时的Mock问题

核心问题

测试时无法获取环境变量中的解密短语,导致Fernet解密抛出InvalidToken错误,需要Mock Fernet的解密逻辑,跳过真实的密钥验证步骤。

解决方案:使用unittest.mock.patch Mock Fernet

方法1:Mock Fernet类及实例的decrypt方法

假设你的业务代码在your_module.py中:

from cryptography.fernet import Fernet

PATH = "some/path/to/key"

class KeyHandler:
    def __init__(self, decrypt_phrase):
        self.decrypt_phrase = decrypt_phrase

    def decrypt_and_save(self, encrypted_data):
        f = Fernet(self.decrypt_phrase)
        decrypted_data = f.decrypt(encrypted_data)
        with open(PATH, "wb") as file:
            file.write(decrypted_data)
        return decrypted_data

测试代码(以pytest为例):

from unittest.mock import patch, MagicMock
from your_module import KeyHandler

def test_decrypt_and_save():
    # 1. 预设模拟的解密结果
    mock_decrypted = b"valid_jwt_secret_key"
    
    # 2. 创建Fernet实例的Mock对象,指定decrypt方法返回预设值
    mock_fernet = MagicMock()
    mock_fernet.decrypt.return_value = mock_decrypted

    # 3. Patch业务代码中使用的Fernet类(关键:patch路径是业务模块中的Fernet引用)
    with patch("your_module.Fernet", return_value=mock_fernet):
        # 初始化Handler,解密短语随便填(不会被真实使用)
        handler = KeyHandler(decrypt_phrase=b"fake_phrase")
        # 调用测试方法
        result = handler.decrypt_and_save(b"fake_encrypted_data")

        # 验证调用逻辑是否符合预期
        mock_fernet.decrypt.assert_called_once_with(b"fake_encrypted_data")
        assert result == mock_decrypted

关键注意点

  • Patch路径要正确:必须patch业务代码中实际导入使用的Fernet,即your_module.Fernet,而非cryptography.fernet.Fernet。因为patch是替换被测试代码中引用的对象,而非原模块的对象。
  • 隔离文件写入:如果不想测试时真实写入文件,可以额外Mockbuiltins.open:
    with patch("your_module.Fernet", return_value=mock_fernet), \
         patch("builtins.open", MagicMock()) as mock_open:
        handler.decrypt_and_save(b"fake_encrypted_data")
        # 验证文件操作
        mock_open.assert_called_once_with("some/path/to/key", "wb")
        mock_open.return_value.__enter__.return_value.write.assert_called_once_with(mock_decrypted)
    

备选方案:在tox中设置测试用环境变量

如果不想Mock,也可以在tox.ini中直接设置测试用的解密短语,避免环境变量缺失:

[testenv]
# 传递系统环境变量(如果本地有设置)
passenv = DECRYPT_PHRASE
# 或者直接设置测试用密钥(需提前生成一个Fernet密钥)
setenv =
    DECRYPT_PHRASE = gAAAAABk...(你的测试用Fernet密钥)

这种方式会走真实的解密逻辑,适合需要验证解密流程正确性的场景,但灵活性不如Mock。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:25:14