Reputation: 1817
from unittest.mock import patch
class A:
def b(self):
return 'HAHAHA A'
a = A()
with patch('__main__.A') as a_mock:
a_mock.b.return_value = 'not working'
print(a.b())
HAHAHA A
>>>
Why doesn't it print 'not working'
? What for is a_mock, then? ______________
Upvotes: 1
Views: 756
Reputation: 1123500
You replaced the whole class with your patch, not the method on the existing class. a = A()
created an instance of A
before you replaced the class, so a.__class__
still references the actual class, not the mock.
Mocking can only ever replace one reference at a time, and not the object referenced. Before the patch, both the names A
and the attribute a.__class__
are references to the class object. You then patched only the A
reference, leaving a.__class__
in place.
In other words, a.__class__
is not patched, only A
, and A().b()
would print not working
.
You'd have to patch just the method on the class, so that a.__class__
still references A
, and a.b
will resolve to the patched A.b
mock:
with patch('__main__.A.b') as b_mock:
b_mock.return_value = 'working as long as you patch the right object'
print(a.b())
Demo:
>>> with patch('__main__.A.b') as b_mock:
... b_mock.return_value = 'working as long as you patch the right object'
... print(a.b())
...
working as long as you patch the right object
You can't, unfortunately, patch the a.__class__
reference with a Mock
; Python only lets you use actual classes for that attribute.
>>> with patch('__main__.a.__class__') as a_class_mock:
... a_class_mock.b.return_value = 'working as long as you patch the right object'
... print(a.b())
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/unittest/mock.py", line 1312, in __enter__
setattr(self.target, self.attribute, new_attr)
TypeError: __class__ must be set to a class, not 'MagicMock' object
Upvotes: 3
Reputation: 6209
You may want to patch your instance instead of your class:
with patch('__main__.a') as a_mock:
a_mock.b.return_value = 'works perfectly ;)'
print(a.b())
Upvotes: 0