Reputation: 11
Hi I am trying to test to see if a method in object A calls another object, object B's, methods. I already have separate tests which tests B's functionality so my goal is just to see if B's method has been called. I am trying to use mocks to create a mock object B, following a method similar to this, but keep getting the following error: AssertionError: Expected 'process' to have been called once. Called 0 times.
Am I doing the mock wrong?
From my understanding, this answer suggested to access the field in sut and set it to a mock, but due to how my code is setup I can not access the other objects.
Example code:
# object B
from abc import ABCMeta
class B(metaclass=ABCMeta):
def process(self):
print('I am B')
# object C
from abc import ABCMeta
class C(metaclass=ABCMeta):
def process(self):
print('I am C')
# object A
from abc import ABCMeta
from b import B
from c import C
class A(metaclass=ABCMeta):
def __init__(self):
self.__known_auto_processes = {}
self.__inti_know_processes()
def process(self, arg):
try:
self.__known_auto_processes[arg].process()
except KeyError as error:
print(f'Invalid arg option {error.args}.')
def __inti_know_processes(self):
self.__known_auto_processes['B'] = B()
self.__known_auto_processes['C'] = C()
Example Test:
import unittest
from unittest.mock import patch
from a import A
class TestA(unittest.TestCase):
@patch("b.B")
def test_b_call(self, mock_b):
a = A()
a.process('B')
mock_b.process.assert_called_once()
Upvotes: 0
Views: 969
Reputation: 501
Your mistake is that you tried to patch the Class's method where it was defined, not where it was used.
When you patch, you should patch an object/method, where they were used. You can refer to this official doc for more details.
As for your examples, they should look like this :
import unittest
from unittest.mock import patch
from a import A
class TestA(unittest.TestCase):
@patch("a.B")
def test_b_call(self, mock_b):
a = A()
a.process('B')
mock_b.process.assert_called_once()
Since you used the B Class
within the a
module, that is where you should patch it.
Upvotes: 0
Reputation: 11
These posts helped me link1 link2. Something like this should work. I think what this does is it creates a mock wrapper around the process in B, as a result, it will count the times it is called.
If you have more insight or a better explanation that would be appreciated.
import unittest
from unittest.mock import patch, PropertyMock
from a import A
from b import B
class TestA(unittest.TestCase):
@patch.object(B, 'process', new_callable=PropertyMock)
def test_b_call(self, mock_b):
a = A()
mock_b.return_value = mock_b.process
a.process('B')
mock_b.process.assert_called_once()
You can also add something like mock_obj.process.return_value = (mock.MagicMock(), mock.MagicMock())
if you code expects something to be returned, in my actual code it expected 2 arguments.
Upvotes: 1