@ mock.patch如何知道每个模拟对象使用哪个参数?

Pre*_*zel 7 python unit-testing mocking

查看此网页:http://www.toptal.com/python/an-introduction-to-mocking-in-python - 作者在Python中讨论了Mocking和Patching,并提供了一个非常可靠的"真实世界"示例.绊倒我的部分是理解单元测试框架如何工作知道哪个模拟对象传递给哪个补丁.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)
Run Code Online (Sandbox Code Playgroud)

代码示例很容易理解.对OS库/模块的硬编码依赖性.首先使用该os.path.isfile()方法检查文件是否存在,如果是,则使用删除它os.remove()

测试/模拟代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from mymodule import rm

import mock
import unittest

class RmTestCase(unittest.TestCase):

    @mock.patch('mymodule.os.path')
    @mock.patch('mymodule.os')
    def test_rm(self, mock_os, mock_path):
        # set up the mock
        mock_path.isfile.return_value = False

        rm("any path")

        # test that the remove call was NOT called.
        self.assertFalse(mock_os.remove.called, "Failed to not remove the file if not present.")

        # make the file 'exist'
        mock_path.isfile.return_value = True

        rm("any path")

        mock_os.remove.assert_called_with("any path")
Run Code Online (Sandbox Code Playgroud)

我想让我感到困惑的是,在测试中传递了2个@Patch调用和2个参数.单元测试框架如何知道mymodule.os.path修补os.path并将其映射到mock_path?在哪里mymodule.os.path定义?

(似乎有很多"魔法"正在进行,我没有遵循它.)

eya*_*lsn 6

它按照装饰器的执行顺序进行,这也是传递给测试方法的参数的顺序......

装饰器执行顺序如下所示:https : //thadeusb.com/weblog/2010/08/23/python_multiple_decorators/

当您按照您编写的方式使用补丁时,它会自动为您创建一个 Mock 实例并将其作为参数传递给您的测试方法。还有另一个版本:

@mock.patch("subprocess.check_output", mock.MagicMock(return_value='True'))
def test_mockCheckOutput(self):
    self.assertTrue(subprocess.check_output(args=[])=='True')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您传递自己的 Mock 对象,在此示例中,当您调用 subprocess.check_output() 时,它将返回“True”

但是,您可以这样做:

def test_mockCheckOutput(self):
    m = mock.MagicMock(return_value='True')
    with mock.patch("subprocess.check_output", m):
        self.assertTrue(subprocess.check_output(args=[])=='True')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以传递您想要的任何模拟项目,因为它将在运行时进行评估... :)