@ mock.patch如何知道要为每个模拟对象使用哪个参数? [英] How does @mock.patch know which parameter to use for each mock object?

查看:100
本文介绍了@ mock.patch如何知道要为每个模拟对象使用哪个参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看此网页: http://www.toptal .com/python/an-introduction-to-mocking-in-python -作者讨论了Python中的模拟和修补,并给出了一个非常可靠的真实世界"示例.让我兴奋的部分是了解单元测试框架的工作方式,从而知道将哪个模拟对象传递给哪个补丁.

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

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)

代码示例非常容易理解.对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")

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

(似乎发生了很多魔术",但我没有关注.)

解决方案

它遵循装饰器的执行顺序,也就是传递给测试方法的参数的顺序...

装饰器的执行顺序如下所示: 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')

在这种情况下,您传递了自己的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')

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

Looking at this webpage: http://www.toptal.com/python/an-introduction-to-mocking-in-python -- The author talks about Mocking and Patching in Python and gives a pretty solid "real-world" example. The part that is tripping me up is understanding how the unit testing frame work knows which mock object gets passed to which patch.

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

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)

Code sample is pretty easy to understand. Hard-coded dependency on the OS library/module. First checks if the file exists using the os.path.isfile() method and if so, removes it using os.remove()

Test/Mock code is as follows:

#!/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")

I guess what's confusing me is that there are 2 @Patch calls and 2 parameters passed in the test. How does the unit testing framework know that mymodule.os.path is patching os.path and that it is mapped to mock_path? And where is mymodule.os.path defined?

(There appears to be a lot of "magic" going on and I'm not following it.)

解决方案

it goes by the order of the execution of the decorators and that is also the order of the parameters passed on to your test method...

order of decorators execution is shown here: https://thadeusb.com/weblog/2010/08/23/python_multiple_decorators/

When you use patch the way you wrote it, a Mock instance it is automatically created for you and passed as a parameter to your test method. there is another version of it:

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

in this case you pass your own Mock object and in this example, when you call subprocess.check_output(), it will return 'True'

you could however do:

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

and in this case you can pass any mock item you want because it will be evaluated during runtime... :)

这篇关于@ mock.patch如何知道要为每个模拟对象使用哪个参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆