ca9163d9
ca9163d9

Reputation: 29159

Patch: AssertionError: Expected '...' to have been called once. Called 0 times

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

Answers (1)

MrBean Bremen
MrBean Bremen

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

Related Questions