简体   繁体   中英

How do I import and monkey patch a Python module that is in a different package from the tests?

My source tree looks like this:

.
├── README.md
├── app
│   ├── __init__.py
│   ├── flask_main.py
│   └── lib.py
├── run_endpoint_check_tests.sh
├── run_flask.sh
├── run_unit_tests.sh
└── tests
    ├── endpoint_checks.py
    └── test_lib.py

flask_main.py (naturally) imports lib.py like this: import roku_lib

But to get test_lib.py to import lib.py , I need to do this:

sys.path.append("app")
from app import lib

And I run the unit tests using this (in run_unit_tests.sh ):

#!/bin/sh
python -m pytest

(I haven't been able to get running pytest to work, which I guess makes sense after reading https://docs.pytest.org/en/latest/goodpractices.html#tests-outside-application-code .)

This unit test fails though:

def test_load_from_s3(mocker, monkeypatch):
    x_mock = mocker.Mock()
    return_mock = mocker.Mock()
    x_mock.Object = mocker.Mock(return_value=return_mock)
    monkeypatch.setattr(lib, 'get_x', lambda: x_mock)

    y = lib.get_x()

    x_mock.Object.assert_called_once()

    ...

I think it fails because calling lib.get_x() results in it importing it's own (copy of?) lib that is not monkey patched.

The same test works when the source tree looks like this:

    .
    ├── README.md
    ├── __init__.py
    ├── lib.py
    ├── uses_lib.py
    └── tests
        ├── __init__.py
        ├── test_uses_lib.py
        └── test_lib.py

And sys.path.append("app") & from app import lib are unnecessary.

But for historical reasons, I must keep flask_main.py in the app package. I could move lib.py into a separate package though, if that solves my problem.

So finally my questions...

How do I fix the imports or monkey patching code (or both) so the monkey patch works?

Is it possible (by adding extra empty __init__.py files where missing, perhaps?) to get the import to work in test_lib.py without sys.path.append("app") ?

I moved lib.py into a libs directory:

.
├── README.md
├── app
│   ├── __init__.py
│   └── flask_main.py
├── libs
│   ├── __init__.py
│   ├── lib_a.py
│   └── lib_b.py
├── run_endpoint_check_tests.sh
├── run_unit_tests.sh
└── tests
    ├── endpoint_checks.py
    ├── test_lib_a.py
    └── test_lib_b.py

(And I split lib.py into lib_a.py and lib_b.py . lib_b.py imports lib_a .)

And I import lib_a.py and lib_b.py the same way in flask_main.py , lib_b.py , and test_lib_a.py & test_lib_b.py :

sys.path.append("..")
from libs import lib_a
from libs import lib_b

Now flask_main.py runs properly and the unit tests pass (with the monkey patch assertions not failing).

Note I deleted run_flask.sh since I now have to run flask_main.py with the app directory as the cwd.

Note also I still have to run python -m pytest ——running pytest leads to ModuleNotFoundErrors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM