I would like to use pytest monkeypatch to mock a class which is imported into a separate module. Is this actually possible, and if so how does one do it? It seems like I have not seen an example for this exact situation. Suppose you have app with and imported class A in something.py
from something import A #Class is imported
class B :
def __init__(self) :
self.instance = A() #class instance is created
def f(self, value) :
return self.instance.g(value)
inside my test.py I want to mock A inside B
from something import B
#this is where I would mock A such that
def mock_A :
def g(self, value) :
return 2*value
#Then I would call B
c = B()
print(c.g(2)) #would be 4
I see how monkeypatch can be used to patch instances of classes, but how is it done for classes that have not yet been instantiated? Is it possible? Thanks!
OneCricketeer
193k20 gold badges147 silver badges277 bronze badges
asked Apr 7, 2020 at 1:07
user3071643
1,5732 gold badges16 silver badges21 bronze badges
1 Answer 1
tested this, works for me:
def test_thing(monkeypatch):
def patched_g(self, value):
return value * 2
monkeypatch.setattr(A, 'g', patched_g)
b = B()
assert b.g(2) == 4
Jonathan
8,9709 gold badges57 silver badges79 bronze badges
answered Apr 7, 2020 at 1:27
yedpodtrzitko
9,4392 gold badges49 silver badges47 bronze badges
Sign up to request clarification or add additional context in comments.
3 Comments
chwi
I do not see why this is the approved answer. Of course it works, but do you then need do
monkeypath for every attribute? It would be simpler to create a mock class containing the methods needed and use the full class with one call to monkeypatch instead of several. Wouldn't it?tonyg
Sometimes you only need to monkeypatch a method or two (for example, if they make API calls that you want to mock).
NeilG
Classic. There's 1 answer. It works. But why is it approved? Even if another answer was provided using
unittest.mock that's not in the terms of the question. We're trying to work with pytest. monkeypatch here. There's enough unittest.mock answers already.lang-py