<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">&lt;<a href="mailto:yonix85@gmail.com">yonix85@gmail.com</a>&gt;</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&#39;m pretty new to the world of testing in python, and there&#39;s a problem I ran into while trying to mock a decorator in the code I&#39;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 &gt;&gt; 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 &gt; 2:</div>


<div>        raise BadArgsError(&quot;arg is bigger than 2&quot;)</div><div><br></div><div>    print &quot;arg is ok&quot;</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(&quot;a.catch_bad_args&quot;, 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 &quot;test_b.py&quot;, line 13, in test_three_raises</div><div>    self.assertRaises(BadArgsError, foo, 3)</div><div>  File &quot;/usr/lib/python2.6/unittest.py&quot;, line 336, in failUnlessRaises</div>


<div>    callableObj(*args, **kwargs)</div><div>  File &quot;/tmp/a.py&quot;, 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 &quot;b.catch_bad_args&quot; 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&#39;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>