Cristhian Boujon
Cristhian Boujon

Reputation: 4190

'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?

Upvotes: 15

Views: 29752

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477533

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')

Upvotes: 27

Cristhian Boujon
Cristhian Boujon

Reputation: 4190

In oriented object case:

class Foo:
    def rm(self, filename):
        self.helper(filename, 5)

    def helper(self, filename, number):
        pass

def test_unix_fs(mocker):
    mocker.patch.object(Foo, 'helper')
    foo = Foo()
    foo.rm('file')
    helper.assert_called_once_with('file', 5)

Upvotes: 5

Related Questions