<div dir="ltr"><div><div class="gmail_quote"><meta charset="utf-8">Hey Yoni,</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Tue, Dec 28, 2010 at 17:32, Yoni Tsafir <span dir="ltr"><<a href="mailto:yonix85@gmail.com">yonix85@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div dir="ltr">Hi guys,<div>I'm pretty new to the world of testing in python, and there's a problem I ran into while trying to mock a decorator in the code I'm testing.</div>
<div>Tell me what am I doing wrong or if this is a missing feature in the mock library.</div>
<div><br></div><div>I have the following code:</div><div><br></div><div>a.py:</div><div>-------</div><div><div>import sys</div><div><br></div><div>class BadArgsError(Exception):</div><div> pass</div><div><br></div><div>
<br></div><div>def catch_bad_args(func):</div><div> def call(*args, **kwargs):</div><div> try:</div><div> return func(*args, **kwargs)</div><div> except BadArgsError, e:</div><div> print >> sys.stderr, e.args[0]</div>
<div> print</div><div> sys.exit(1)</div><div><br></div><div> call.__name__ = func.__name__</div><div> call.__dict__ = func.__dict__</div><div> call.__doc__ = func.__doc__</div><div> return call</div>
<div style="text-decoration:underline"><br></div></div><div>b.py</div><div>------</div><div><div>from a import BadArgsError, catch_bad_args</div><div><br></div><div>@catch_bad_args</div><div>def foo(arg):</div><div> if arg > 2:</div>
<div> raise BadArgsError("arg is bigger than 2")</div><div><br></div><div> print "arg is ok"</div></div><div><br></div><div>test_b.py</div><div>-------------</div><div><div>import unittest</div>
<div>from b import foo</div><div>from a import BadArgsError</div><div>from mock import patch</div><div> </div><div>def do_nothing_decorator(func):</div><div> return func</div><div> </div><div> </div><div>
class BTest(unittest.TestCase):</div>
<div> @patch("a.catch_bad_args", do_nothing_decorator)</div><div> def test_three_raises(self):</div><div> self.assertRaises(BadArgsError, foo, 3)</div><div><div><br></div><div><br></div>
<div><div>Now running the tests:</div></div><div>-------------------------------</div><div><div># python test_b.py</div><div>arg is bigger than 2</div><div>
<br></div><div>E</div><div>======================================================================</div><div>ERROR: test_three_raises (__main__.BTest)</div><div>----------------------------------------------------------------------</div>
<div>Traceback (most recent call last):</div><div> File "test_b.py", line 13, in test_three_raises</div><div> self.assertRaises(BadArgsError, foo, 3)</div><div> File "/usr/lib/python2.6/unittest.py", line 336, in failUnlessRaises</div>
<div> callableObj(*args, **kwargs)</div><div> File "/tmp/a.py", line 14, in call</div><div> sys.exit(1)</div><div>SystemExit: 1</div><div><br></div><div>----------------------------------------------------------------------</div>
<div>Ran 1 test in 0.014s</div><div><br></div><div>FAILED (errors=1)</div></div></div></div><div><br></div><div><br></div><div>What am I doing wrong? I tried to change the patch to "b.catch_bad_args" and I get the same results, I also tried @patch.object and other combinations... No help</div>
<div><br></div></div></blockquote><div><br></div><div><meta charset="utf-8"><div>AFAICT, the problem is that once you import the file the function is evaluated and the decorator is applied to it, before you patch it.</div>
<div>I think that instead of messing with patching decorators, you can make your decorator export the wrapped function, for example by setting an attribute .decorated on the new function so you'd be able to access it freely in your tests.</div>
<div><br></div><div>BTW, instead of copying yourself the function attributes, it is advised to use functools.wraps</div><div><br></div><div>Hope this helps,</div><div>Aviv</div></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div dir="ltr"><div></div><div><br></div><div>Thanks a lot!</div></div>
<br>_______________________________________________<br>
testing-in-python mailing list<br>
<a href="mailto:testing-in-python@lists.idyll.org">testing-in-python@lists.idyll.org</a><br>
<a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">http://lists.idyll.org/listinfo/testing-in-python</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Aviv Ben-Yosef<br>Miracle Max: You rush a miracle man, you get rotten miracles.<br>
</div></div>