如何使用补丁相对路径进行模拟?

Sar*_*ica 24 python unit-testing mocking

我在python测试文件中有这样的东西:

from mock import patch,
from ..monkey import ook
[...]
@patch('monkey.ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
    self.assertIsNone(ook())
    mock_ook.run.assert_called_once_with('')
Run Code Online (Sandbox Code Playgroud)

当我运行这个测试时,我得到了一个ImportError: No module named monkey.显然,我修补的道路是不对的.但是,我不知道如何使它权利,没有搞乱sys.pathPYTHONPATH.

有什么指针吗?

Dan*_*aro 17

从我收集到的,使用mock,你需要在修补时提供虚线名称.幸运的是,每个模块都可以访问__name__包含模块名称的特殊模块级变量.使用此方法,如果要修改模块本地的变量,您应该可以执行以下操作:

import mock
import unittest

ook = lambda: "the ook"


class OokTest(unittest.TestCase):

    def test_ook(self):
        with mock.patch(__name__ + '.ook', return_value=None):
            self.assertIsNone(ook())
        self.assertEquals(ook(), "the ook")

    # the patch decorator should work the same way, I just tend to use the
    # context manager out of personal preference
    @mock.patch(__name__ + '.ook', return_value=None)
    def test_ook_2(self, mock_ook):
        self.assertIsNone(ook())
Run Code Online (Sandbox Code Playgroud)

假设您已将该文件保存为quicktest.py,则单元测试会给出以下结果:

$ python -m unittest quicktest
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK
Run Code Online (Sandbox Code Playgroud)

当然,在包中from a.b import c给出一个简单的变量c,所以这个机制应该有效.

  • 您还可以使用“__package__”代替“_name__”来访问当前目录。 (2认同)

bal*_*alu 16

我使用了leo-the-manic的解决方案直到我遇到这个问题patch.object- 这看起来对我来说更好:

from unittest.mock import patch,
from .. import monkey
[...]
@patch.object(monkey, 'ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
    self.assertIsNone(monkey.ook())
    mock_ook.run.assert_called_once_with('')
Run Code Online (Sandbox Code Playgroud)

好处:

  • 不需要样板代码 __name__ + '.object_to_be_mocked'
  • 测试用例的所有依赖关系都在文件的开头清楚地声明为import语句.

缺点:

  • 你不能这样做@patch.object(amazon.jungle.monkey, 'ook', …),但需要做的amazon.jungle.monkey并获得'amazon.jungle.monkey.ook'通过from ..monkey import ook,即from .. import monkey.在我需要经常写这个的情况下,ook为方便起见,我将添加到import语句中.


moo*_*ima 5

基于公认的答案,我相信这是实现预期目标的最简洁方法:

from mock import patch
from .. import monkey

@patch(monkey.__name__+'.ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
    self.assertIsNone(monkey.ook())
    mock_ook.run.assert_called_once_with('')
Run Code Online (Sandbox Code Playgroud)