Suppose there are two packages in a project:
# some_package/foo.py: def bar(): print('hello')
# another_package/function.py from some_package.foo import bar def call_bar(): # ... code ... bar() # ... code ...
I want to test
another_package.function.call_bar mocking out
some_package.foo.bar because it has some network I/O I want to avoid.
Here is a test:
# tests/test_bar.py from another_package.function import call_bar def test_bar(monkeypatch): monkeypatch.setattr('some_package.foo.bar', lambda: print('patched')) call_bar() assert True
To my surprise it outputs
hello instead of
patched. I tried to debug this thing, putting an IPDB breakpoint in the test. When I manually import
some_package.foo.bar after the breakpoint and call
bar() I get
On my real project the situation is even more interesting. If I invoke pytest in the project root my function isn't patched, but when I specify
tests/test_bar.py as an argument - it works.
As far as I understand it has something to do with the
from some_package.foo import bar statement. If it's being executed before monkeypatching is happening then patching fails. But on the condensed test setup from the example above patching does not work in both cases.
And why does it work in IPDB REPL after hitting a breakpoint?