17

I've a class in python that contains a static method. I want to mock.patch it in order to see if it was called. When trying to do it I get an error: AttributeError: path.to.A does not have the attribute 'foo'

My setup can be simplified to:

class A:
    @staticMethod
    def foo():
        bla bla

Now the test code that fails with error:

def test():
    with mock.patch.object("A", "foo") as mock_helper:
        mock_helper.return_value = ""
        A.some_other_static_function_that_could_call_foo()
        assert mock_helper.call_count == 1

3 Answers 3

21

You can always use patch as a decorator, my preferred way of patching things:

from mock import patch

@patch('absolute.path.to.class.A.foo')
def test(mock_foo):
    mock_foo.return_value = ''
    # ... continue with test here

EDIT: Your error seems to hint that you have a problem elsewhere in your code. Possibly some signal or trigger that requires this method that is failing?

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the response. I've tried your syntax and got the same error. Maybe I need to mock both parent class and the static function separately. I'll continue to investigate..
I also have the same problem. If you found a solution, please post it! ^_^
After trying lots of different approaches, I can confirm that this solution is not only the simplest one, but also that it works for static functions too.
It seams to be from unittest.mock import patch in Python 3
7

I was getting that same error message when trying to patch a method using the @patch decorator.

Here is the full error I got.

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/tornado/testing.py", line 136, in __call__ 
    result = self.orig_method(*args, **kwargs)
File "/usr/local/lib/python3.6/unittest/mock.py", line 1171, in patched     
    arg = patching.__enter__()
File "/usr/local/lib/python3.6/unittest/mock.py", line 1243, in __enter__
    original, local = self.get_original()
File "/usr/local/lib/python3.6/unittest/mock.py", line 1217, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <module 'py-repo.models.Device' from
        '/usr/share/projects/py-repo/models/Device.py'> does not have the attribute 'get_device_from_db'

What I ended up doing to fix this was changing the patch decorator I used

from @patch('py-repo.models.Device.get_device_from_db')

to @patch.object(DeviceModel, 'get_device_from_db')

I really wish I could explain further why that was the issue but I'm still pretty new to Python myself. The patch documentation was especially helpful in figuring out what was available to work with. Important: I should note that get_device_from_db uses the @staticmethod decorator which may be changing things. Hope it helps though.

1 Comment

That actualy worked for @staticmethod, thank you for sharing.
0

What worked for me:

@patch.object(RedisXComBackend, '_handle_conn')
def test_xcoms(self, mock_method: MagicMock):
    mock_method.return_value = fakeredis.FakeStrictRedis()

'_handle_conn' (static function) looks like this:

    @staticmethod
    def _handle_conn():
        redis_hook = RedisHook()
        conn: Redis = redis_hook.get_conn()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.