[TIP] Revisit mocking function with arguments with decorator applied

John Wong gokoproject at gmail.com
Wed Dec 9 08:54:00 PST 2015


Hi

There was a discussion about a similar question back in 2010 [1], but I am
not aware of any solution.

Suppose you have a.py and test.py

#a.py
import contextlib

@contextlib.contextmanager
def foo(a):
    yield "123"

def bar():
    with foo(1) as f:
        return f

#test.py
import unittest
from mock import patch, Mock, MagicMock, mock_open

import a

class TestFoo(unittest.TestCase):
    def test_foo(self):
        with patch("a.foo", new=MagicMock) as f:
            f.return_value = "456"
            self.assertEqual(a.bar(), "456")

if __name__ == "__main__":
    unittest.main()

This won't work as foo takes an argument.  I am getting the following
exception:
======================================================================
ERROR: test_foo (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test1.py", line 9, in test_foo
    self.assertEqual(a.bar(), "456")
  File "/private/tmp/a.py", line 8, in bar
    with foo(1) as f:
AttributeError: __exit__

I tried to first patch the context manager decorator, and then patch a.foo
(suggested in [2]), but I am still getting the same exact error. If I don't
have the argument, the code above (using new=MagicMock) will work.

Has anyone came up with a solution for this problem yet? I can't imagine I
am the only one having this issue.

Thank you.

[1]:
http://lists.idyll.org/pipermail/testing-in-python/2010-December/003703.html
[2]: http://jamescooke.info/things-to-remember-about-decorators.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20151209/f766bd87/attachment-0001.htm>


More information about the testing-in-python mailing list