0

I'm writing unit tests for the following the following class.

module1/node_base.py

@dataclass
class NodeBase(metaclass=ABCMeta):
    account: AccountBase
    name: str
    ec2_id: str = ''

    def start(self):
        self.account.session.resource('ec2').instances.filter(
            InstanceIds=[self.ec2_id]).start()

self.account.session is AWS session. How to write the test function? (to check if filter() is called with parameter InstanceIds=[self.ec2_id] and start() is called?)

test_start.py

from module1.node_base import NodeBase

class Node(NodeBase):
    '''Node'''

@pytest.fixture
def sut() -> Node:
    session = Mock()

    def get_resource():
        instances = Mock()
        def get_filter(filters):
            def get_start():
                pass
            return get_start
        instances.filter = get_filter
        return instances

    session.resource = get_resource()
    account = Mock() 
    account.session = session
    return Node(account=account, name='Test')

def test_start(sut):
    sut.start()
    assert sut.account.session.resource('ec2').instances.filter.call_count == 1
    assert sut.account.session.resource('ec2').instances.filter().start.call_count == 1

It seems very verbose to setup the fixture. Is it a simpler approach to test it?

How to test if filter() is called with a particular parameter ['some_id']?

ca9163d9
  • 27,283
  • 64
  • 210
  • 413

1 Answers1

0

You can use patch to assert whether it is being called with a particular parameter. For example:

    @patch('path.to.filter.function')
    def func1(mock_filter):                       // Test case for filter function
         id = '1234'
         parameter = '1234'
         filter(id)                              // Calling the function here
         mock_filter.assert_called_with(parameter)

Here, for the example I'm calling the filter function with value '1234', and later checking if it was called with the same value('1234') or not.

It will return true if the function is called with the parameter you have defined.

Prats
  • 649
  • 2
  • 15
  • Should that be `mock_filter.filter(id)`? Or is `unittest.mock.patch` doing more magic than I'm aware of? – Karl Knechtel Jan 30 '22 at 10:16
  • Mock_filter can also be thought of as more of an alias or a reference name for the filter function, so while calling the function it should only be filter(id) – Prats Jan 30 '22 at 10:42
  • I added `@patch('module1.node_base.NodeBase.start.self.account.session.resource("ec2").instances.filter')`, but it got the error of `ModuleNotFoundError: No module named 'module1.node_base.NodeBase'; 'module1.node_base' is not a package` – ca9163d9 Jan 30 '22 at 18:32
  • I apologise for not mentioning earlier, but it should be the path where the function is declared and not where it is being called.. – Prats Jan 30 '22 at 18:50
  • Maybe this will help you out: https://stackoverflow.com/questions/47576348/python-mock-assert-called-with – Prats Jan 30 '22 at 18:52