Python 2.7和3.6之间的@patch行为不同(使用模拟)

时间:2018-11-21 01:36:03

标签: python python-3.x python-2.7 mocking patch

@patch在2.7和3.6下似乎不会产生相同的行为。

这是我的项目结构:

project/
    foo.py
    bar.py
    lol.py
tests/
    test_project.py

foo.py:

class Foo:
    pass

bar.py(导入Foo):

from project.foo import Foo

class Bar:
    def __init__(self):
        f = Foo()

lol.py(导入栏):

from bar import Bar

class Lol:
    def __init__(self):
        b = Bar()

由于bar.py使用from project.foo import Foo导入了Foo,因此我正在修补bar.Foo(根据where to patch文档):

test_bar.py:

from project import lol
from project import bar

@patch('bar.Foo')  # Works in 3.6, fails with 2.7
def test_lol(mock_Foo):
    l = lol.Lol()
    mock_Foo.assert_called()

此设置可在Python 3.6中正确运行,但在2.7中将失败(Foo无法得到修补)。

但是,如果我将设置切换为:

test_bar.py:

from project import lol
# from project import bar # No need to import bar anymore

@patch('project.bar.Foo')  # Works in 2.7, fails with 3.6
def test_lol(mock_Foo):
    l = lol.Lol()
    mock_Foo.assert_called()

它在2.7中有效,但在3.6中不可用。

使用@patch使其在python版本之间产生一致的结果的推荐方法是什么?

注意:此问题仅在我测试lol.py时出现。如果我从单元测试中调用bar.py,则使用第二个设置@patch('cookie_test.bar.Foo')可以获得一致的结果,并且它在2.7和3.6中都可以使用。

1 个答案:

答案 0 :(得分:1)

__init__.py文件添加到您的project目录,并更改Barlol.py的导入后,我无法使用2.7和3.6复制差异:

from project.bar import Bar

无论哪种情况,您都不需要在测试中导入bar-模拟程序通过解析传递给bar装饰器的字符串来查找mock

我怀疑您看到的错误是由于Python 3使用绝对导入(https://www.python.org/dev/peps/pep-0328/