Search code examples
pythonpython-3.xmockingpytest

'function' object has no attribute 'assert_called_once_with'


I'm trying to run the following test using pytest and pytest_mock

def rm(filename):
    helper(filename, 5)

def helper(filename):
    pass

def test_unix_fs(mocker):
    mocker.patch('module.helper')
    rm('file')
    helper.assert_called_once_with('file', 5)

But I get exception AttributeError: 'function' object has no attribute 'assert_called_once_with'

What am I doing wrong?


Solution

  • You can not perform a .assert_called_once_with function on a vanilla function: you first need to wrap it with the mock.create_autospec [python-doc] decorator. So for instance:

    import unittest.mock as mock
    
    def rm(filename):
        helper(filename, 5)
    
    def helper(filename):
        pass
    
    helper = mock.create_autospec(helper)
    
    def test_unix_fs(mocker):
        mocker.patch('module.helper')
        rm('file')
        helper.assert_called_once_with('file', 5)

    Or more elegantly:

    import unittest.mock as mock
    
    def rm(filename):
        helper(filename, 5)
    
    @mock.create_autospec
    def helper(filename):
        pass
    
    def test_unix_fs(mocker):
        mocker.patch('module.helper')
        rm('file')
        helper.assert_called_once_with('file', 5)

    Note that the assertion will fail, since you call it only with 'file'. So a valid test would be:

    import unittest.mock as mock
    
    def rm(filename):
        helper(filename, 5)
    
    @mock.create_autospec
    def helper(filename):
        pass
    
    def test_unix_fs(mocker):
        mocker.patch('module.helper')
        rm('file')
        helper.assert_called_once_with('file')

    EDIT: In case the function is defined in some module, you can wrap it in a decorator locally. For example:

    import unittest.mock as mock
    from some_module import some_function
    
    some_function = mock.create_autospec(some_function)
    
    def test_unix_fs(mocker):
        some_function('file')
        some_function.assert_called_once_with('file')