2

I'm having a problem trying to patch a static method, no matter what i've tried the original method is still being ran. I'll illustrate an example below.

file A

import B
from unittest.mock import patch
from unittest import mock
import asynctest
import unittest

class Test(asynctest.TestCase):
    @patch('B.OT._func')
    async def test(self, mock_func):
        mock_func.return_value = mock.MagicMock()
        await B.foo()
        mock_func.assert_called_once()
if __name__ == '__main__':
    unittest.main()

file B

from path.C import OT
  
async def foo():
    print('B')
    return OT._func()

path(folder)/file C


class OT:
    @staticmethod
    def _func():
        print('c')
        return True

Problem

I'm having issues mocking the return value for OT._func(). Whatever I try to patch in file A doesn't stop _func() from running in class B. If the test case is ran it prints out 'c' instead of patching the function. My desired outcome is to patch out _func and have it return something else.

Edit: The issue seems to be with the async portion of the test, if the async is removed it works. A workaround for now is using the context manager version (with keyword) to patch stuff.

7
  • You must provide a minimal reproducible example. from c.TestClass import OT would throw an ImportError, there is no OT in c, and TestClass is a class inside c, you can't make it part of the import path, which can only contain modules/packages Commented Sep 2, 2021 at 17:40
  • Dude, the code still doesn't even compile. There is also no class B. And again, it still isn't clear what behavior you are expecting Commented Sep 2, 2021 at 18:24
  • 1
    It looks like you're attempting to patch a function on an object, which means you want to patch the object with patch.objec(). See this. Commented Sep 2, 2021 at 18:27
  • @NathanielFord Hi, I've tried that as well by using '@patch.object(B.OT, '_func')' instead of '@patch' and it still doesn't work. Commented Sep 2, 2021 at 18:33
  • @juanpa.arrivillaga I made a few changes to make it more clear. I copy paste the code and it runs. Also there is no class B, it is running a function defined in that file. Commented Sep 2, 2021 at 18:34

1 Answer 1

1

After looking into it more it seems to be an issue with async and the '@patch' decorator specifically (and possible python 3.7). A simple workaround is to using patching alongside the 'with' keyword. This will bypass the patch decorator not working for async functions.

Alternatively, upgrading from python 3.7.2 to 3.8.2 also fixed the issue and allows patch decorators to work with async functions.

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

1 Comment

Interesting! I did not know about that quirk. There is a good explanation of it here: bugs.python.org/issue36996

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.