monkeypatch conftest中需要导入的一个函数

monkeypatch a function that needs to be imported in conftest

我正在尝试使用 pytest.monkeypatch 来修补我在另一个文件中定义的函数。然后我需要从另一个依赖于此的函数修补一个函数 monkeypatch。这是一个简单的例子

# class_def.py
class C:
    def __init__(self):
        # Normally, there is something that makes self.p
        # that will use a file that will exist on production
        raise FileNotFoundError

def factory():
    print('in factory')
    return C()

----
# function_def.py
from .class_def import factory

foo = factory()

def bar():
    return 0

----
# conftest.py
from unittest.mock import MagicMock

import pytest

import playground.class_def

@pytest.fixture(autouse=True)
def patch_c(monkeypatch):
    fake_c = MagicMock()
    def factory():
        print('in monkey factory')
        return fake_c
    monkeypatch.setattr('playground.class_def.factory', factory)

from .function_def import bar

# Then I would patch bar

和 运行 pytest . 将失败并显示 FileNotFoundError。我相信发生这种情况是因为我在 function_def.py 的顶层调用 foo = factory()。我预计这不会发生,因为我在执行此导入之前正在修补 factory,但这似乎没有发生。有没有办法确保这个 monkeypatch.setattrconftest.pyfrom .function_def import bar 之前生效?

此外,文件结构看起来像

playground
|--- __init__.py
|--- conftest.py
|--- class_def.py
|--- function_def

您可以直接访问要更改的属性。你根本不需要 monkeypatch。

这是我的树:

$ tree .
.
├── a.py
├── b.py
├── __init__.py
└── test_a.py

0 directories, 4 files

a.py

class A:
    def __init__(self):
        raise Exception

def factory():
    return A()

b.py

import a

print(a.factory())

test_a.py

import a


def test_a():
    def fake_factory():
        return 'A'
    a.factory = fake_factory
    import b

有效:

$ pytest
=============================================================================================== test session starts ===============================================================================================
platform linux -- Python 3.6.5, pytest-3.5.1, py-1.5.3, pluggy-0.6.0
rootdir: /home/ahorgnies/test/monkeypatch, inifile:
plugins: remotedata-0.2.1, openfiles-0.3.0, doctestplus-0.1.3, arraydiff-0.2
collected 1 item                                                                                                                                                                                                  

test_a.py .                                                                                                                                                                                                 [100%]

============================================================================================ 1 passed in 0.01 seconds =============================================================================================