I have following project structure:
├───pa
│ |───__init__.py
| |─── a1.py
| |─── test_a1.py
|
├───pb
│ |───__init__.py
| |─── b1.py
With following code: b1.py:
class B1:
def __init__(self):
self.text = "Unmocked_B1"
def get_text(self):
return self.text
pb.__init__.py:
from .b1 import B1
a1.py:
from src.pb import B1
class A1:
def __init__(self):
self.b = B1()
def get_text(self):
return self.b.get_text()
pa.__init__.py:
from .a1 import A1
And I want to mock self.b in class A1 using unittest.mock.patch in such way that following code in test_a1.py will print "Mocked B1"
test_a1.py:
from unittest import TestCase
from unittest.mock import patch, PropertyMock
from . import A1
class TestB1(TestCase):
@patch('Some args')
def test_get_text(self, mocked_b1):
# Some code
a1 = A1()
print(a1.get_text()) # Should print: Mocked B1
I tried both mocking B1 import with:
@patch('src.pb.b1.B1')
def test_get_text(self, mocked_b1):
mocked_b1.get_text.return_value = 'Mocked B1'
a1 = A1()
print(a1.get_text()) # Should print: Mocked B1
And mocking property of a1 with property mock:
@patch('pa.a1.A1.b', new_callable=PropertyMock)
def test_get_text(self, mocked_b):
mocked_b.get_text.return_value = 'Mocked B1'
a1 = A1()
print(a1.get_text()) # Should print: Mocked B1
Which does not seem to work even when I make attribute b inside A1 static instead of dynamic.
Is there a way to mock this attribute? It would be perfect if it would work on dynamic attribute as shown earlier.
I'm using python 3.10
CodePudding user response:
Try the following sintax that uses patch.object
and context manager (instruction with
):
class TestB1(TestCase):
def test_get_text(self):
a1 = A1()
with patch.object(a1, "b") as mocked_b1:
mocked_b1.get_text.return_value = 'Mocked B1'
print(a1.get_text()) # Prints: Mocked B1
CodePudding user response:
Thank you frankfalse for answer of course similar solution with patch decorator also works (I discovered it this morning):
@patch('src.pa.a1.B1')
def test_get_text(self, mocked_B1):
instance = mocked_B1.return_value
instance.get_text.return_value = 'Mocked B1'
a1 = A1()
print(a1.get_text()) # Prints: Mocked B1
Don't know if there is solution with property mock