Reputation: 29159
I have the following class to be tested.
mod1/file1.py
@dataclass
class Base(metaclass=ABCMeta):
account: Account
ec2_id: str = ""
def start(self):
self.account.session.resource("ec2").instances.filter(
InstanceIds=[self.ec2_id]
).start()
And I created the following test,
from unittest.mock import Mock, patch
@patch('mod1.file1.Base')
def test_start(sut):
sut.account = Mock()
sut.ec2_id = 'test'
sut.start() # sut.return_value.start() gets the same error
sut.account.session.resource('ec2').instances.filter.assert_called_once()
However, the test failed with error
AssertionError: Expected 'filter' to have been called once. Called 0 times.
Upvotes: 2
Views: 18488
Reputation: 16815
The problem with the code is that you are mocking the object that you want to test. You have to mock any objects instantiated by your sut
that you don't want to get created (because of unwanted side effect or complex initialization).
If an object is mocked, it cannot be tested, so calling patched object sut
is most certainly wrong.
In your case you need to instantiate the real system under test, e.g. the dataclass, and only mock Account
(as you do), so something like this should work:
def test_start():
sut = Base()
sut.account = Mock()
sut.start()
sut.account.session.resource('ec2').instances.filter.assert_called_once()
Note that setting sut.ec2_id
has no impact, because filter
is mocked and the arguments don't matter.
If this does really test the functionality you need to test is another matter.
Upvotes: 3