Is there a way to monkey patch a class inside a module before the module body is executed in python?
The problem here is that when you import
ed the main.py
file, it executed the code a = A(4)
using the real implementation of the class A
. Then the rest of your test.py
was executed and you replaced the A
reference, but it was too late.
You can check that by adding in your test :
print(__name__) # __main__
print(main.__name__) # so70731368_main
print(A.__module__) # __main__
print(main.A.__module__) # __main__
print(main.a.__class__.__module__) # so70731368_main
Here, __main__
is a bit confusing but that's how Python call the first file you run (in your case test.py
). The a
instance is declared in the so70731368_main
module, and it used the A
class from the same module, you just changed A
after the fact with the definition from the test file (__main__
).
The fact that you need to patch two definitions (A
and a
) defined in the same file is very tricky. unittest.mock.patch
is not powerful enough to patch inside an import (it patches after the import).
You can not, in a clean and simple way, prevent a
to be instantiated as a main.A
(real) class and get printed. What you can do is patch it after, for later uses, that is what you showed.
To answer directly your question : "patching" means replacing one reference by another, so the reference has to already be defined. In your example, it would require to patch between the class definition and the class instantiation (for the print
to not use the real a
), which is not supported.
There is no simple solution to this problem. If you have control over the code of the main.py
file, then try to change it so that it does not instantiate a
at import time.