首页 > 解决方案 > mock.patch 忽略完全导入函数的原因是什么?

问题描述

今天我意识到unittest.mock.patch如何导入函数很重要。根据使用的mock.patch呼叫工作方式或被忽略的方式。在 Python 中,我们通常导入一个函数:

如果我使用Amock.patch就像一个魅力import os,但如果我修补一个from os import system.

示例 1:使用导入

import os
from unittest import mock


def echo():
    os.system('echo "Hello"')


with mock.patch('os.system') as mocked:
    print(mocked)
    mocked.side_effect = Exception('Patch works!')
    echo()

示例 1 的输出

<MagicMock name='system' id='140037358656760'>

Traceback (most recent call last):
  File "/.../config/scratches/scratch_7.py", line 12, in <module>
    echo()
  File "/.../config/scratches/scratch_7.py", line 6, in echo
    os.system('echo "Hello"')
  File "/.../python3.5/unittest/mock.py", line 917, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/.../python3.5/unittest/mock.py", line 973, in _mock_call
    raise effect
Exception: Patch works!

示例 2:使用全功能 import 和 from-import

os.system当我完全导入mock.patch忽略mocked.side_effect.

from os import system
from unittest import mock


def echo():
    system('echo "Hello"')


with mock.patch('os.system') as mocked:
    print(mocked)
    mocked.side_effect = Exception('Patching does not work!')
    echo()

    print('Patch was ignored!')

示例 2 的输出

<MagicMock name='system' id='139851175427376'>
Hello
Patch was ignored!

在这两种情况下,我都没有收到错误,并且mock可以找到os.system有效路径。但是,在第二种情况下,该功能未正确修补。

标签: pythonpython-3.xpython-unittestpython-mock

解决方案


当你这样做时from os import system,你会得到一个名为system指向os.system函数的变量。稍后,您通过修补将不同的功能分配os.system给,但system始终指向旧功能。这与以下工作的原因相同:

tmp = a
a = b
b = tmp

它不会在第一个示例中发生,因为您os.system在模拟之前引用了它。要修复您的第二个示例,我将使用以下内容:

from os import system
from unittest import mock

def echo():
    system('echo "Hello"')

with mock.patch('__main__.system') as mocked:
    print(mocked)
    mocked.side_effect = Exception('Patching does not work!')
    echo()

    print('Patch was ignored!')

这样,您可以确保修补正确的参考。这是一个相当普遍的模式。如果echo函数位于名为 的文件中echo.py,则补丁调用看起来像with mock.patch('echo.system').


推荐阅读