I have a Gateway class that has contains an instance of a Resource class. I've already done my unit testing on Resource, and to simplify testing, Resource is injected into Gateway as a dependency at initialization:
class Gateway:
def __init__(self, resource):
self._resource = resource(Master)
def list_things(self):
return self._resource.list_resource()
Now I'd like write unit test for Gateway to verify that resource.list_resource()
gets called as a result of calling gateway.list_things()
. My best attempt doesn't work:
class TestGateway(unittest.TestCase):
def test_list_things(self):
mock_resource = Mock()
g = modbus.gateway.Gateway(mock_resource)
g.list_things()
mock_resource.list_resource.assert_called_once()
The result:
AssertionError: Expected 'list_resource' to have been called once. Called 0 times.
What am I missing?
In the actual use case of the mock_resource
that you passed into Gateway
for your test case, the constructor in Gateway
actually makes a further call to the resource
argument as a constructor, so that what the test expects is actually emulating the checking of the call against the class method, not the instance method of the mock_resource
. Demonstrating this using just the minimum number of statements can be done using the following:
>>> mock_resource = Mock()
>>> self_resource = mock_resource('Master') # emulate Gateway.__init__
>>> self_resource.list_resource() # emulate Gateway.list_things
<Mock name='mock().list_resource()' id='140441464498496'>
>>> mock_resource.list_resource.assert_called_once() # test_list_things
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/unittest/mock.py", line 795, in assert_called_once
raise AssertionError(msg)
AssertionError: Expected 'list_resource' to have been called once. Called 0 times.
>>> self_resource.list_resource.assert_called_once() # test the _actual_ call
>>>
Note that I had assigned self_resource
to emulate the self._resource = resource(Master)
statement in the constructor for Resource
, and the mismatching of the test vs. what is actually executed should now be apparent.
To fix this, the test should check the call like so:
def test_list_things(self):
mock_resource = Mock()
g = modbus.gateway.Gateway(mock_resource)
g.list_things()
# mock_resource.list_resource.assert_called_once()
g._resource.list_resource.assert_called_once()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.