python - 使用 unittest.mock 在 python 中修补 SMTP 客户端

标签 python python-3.x unit-testing mocking python-unittest.mock

我想模拟 SMTP 客户端表单 smtplib 的生成。以下代码:

from smtplib import SMTP
from unittest.mock import patch

with patch('smtplib.SMTP') as smtp:
    print(SMTP, smtp)

返回

<class 'smtplib.SMTP'> <MagicMock name='SMTP' id='140024329860320'>

暗示补丁失败。

编辑: 有趣的是 Monkey Patching as described here给出相同的结果。

import smtplib
from smtplib import SMTP
from unittest.mock import MagicMock

smtp = MagicMock()
smtplib.SMTP = smtp
print(SMTP, smtp)

最佳答案

我几乎不做任何修补,但我相信你修补的太晚了,或者打错了。 SMTP 已经导入,导致直接引用原始类——它将不再在 smtplib 中查找。相反,您需要修补该引用。让我们使用一个更现实的示例,其中您有 module.pytest_module.py

module.py:

import smtplib
from smtplib import SMTP # Basically a local variable

def get_smtp_unqualified():
    return SMTP # Doing a lookup in this module

def get_smtp_qualified():
    return smtplib.SMTP # Doing a lookup in smtplib

test_module.py

import unittest
from unittest import patch
from module import get_smtp_unqualified, get_smtp_qualified

class ModuleTest(unittest.TestCase):
    def test_get_smtp_unqualified(self):
        with patch('module.SMTP') as smtp:
            self.assertIs(smtp, get_smtp_unqualified())

    def test_get_smtp_qualified_local(self):
        with patch('module.smtplib.SMTP') as smtp:
            self.assertIs(smtp, get_smtp_qualified())

    def test_get_smtp_qualified_global(self):
        with patch('smtplib.SMTP') as smtp:
            self.assertIs(smtp, get_smtp_qualified())

只要您在查找之前及时打补丁,它就会如您所愿——3 次通过测试。最早的时间是在导入除 unittest 之外的任何其他模块之前。那么这些模块还没有导入smtplib.SMTP。更多关于 here .但是,当您的测试分为多个模块时,它会变得很棘手。

打补丁本质上是脏的。你在搞乱别人的内部结构。为了让它发挥作用,你必须从内部看。如果内部发生变化,测试就会中断。这就是为什么您应该将其视为最后的手段并更喜欢不同的方法,例如依赖注入(inject)。这是一个完全不同的话题,但无论如何,不​​要依赖补丁来防止消息外传——还要更改配置!

关于python - 使用 unittest.mock 在 python 中修补 SMTP 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47815762/

相关文章:

python - 在 Python 中使用列表推导式进行质因数分解

python - 为什么相同正则表达式的 python re.findall() 对于两个等效的输入字符串产生不同的结果?

python-3.x - 导入 tensorflow_datasets 时出现错误

python:无状态函数库设计

python - 使用 Python Mock 库监视内部方法调用

java - 使用 Mockito 测试 Mono 和 Flux

python - 厄密矩阵的 logm 函数返回非厄密矩阵

python - Numpy:ValueError:使用序列设置数组元素

Python:不完整的 URL 正则表达式输出

python - 如何在 python 中模拟 pyplot.show(以防止显示图)